I wrote a paint class, and added the jpanel to the frame, but it's getting called twice for some reason, as I put a print statement inside the graphics method, and it printed it twice. The codes below are all the codes I have in my package.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Paint extends JPanel {
static Paint paint = new Paint();
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Hello");
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(paint);
frame.pack();
frame.setLocation(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I tried your code and paintComponent it's not called twice every time. I don't think you have the control on when the JFrame is calling pack() when you call setVisible. It may depends on how your OS manage the windows.
Related
I wanted to know if it is possible to use/make a function in another Class to draw an image/oval and then call it in the paint public void in our main Class.
If I have
public class Trydraw{
public void drawrcircle(Graphics g){
g.setColor(Color.RED);
g.drawOval(0, 0, 20,20);
g.fillOval(0,0,20,20);
}
}
And then call it here this way
import java.awt.GridLayout;
import javax.swing.*;
import java.awt.*;
public class Display extends JPanel{
public static void main(String[]haha){
JFrame frame = new JFrame();
frame.setSize(800, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void paint(Graphics g){
super.paint(g);
Trydraw l = new Trydraw();
l.drawrcircle(g);
}
}
Thanks for your future help.
Yes you can, if I get your question correctly.
Your sample code works for me if I add
frame.add(new Display());
to the end of your
public static void main(String[] haha)
method.
With your snippet the paint(g) method will never be called, because it will be executed with the initialization of the JPanel which will be initialized with the initialization the Display class (because of inheritance).
You probably want to create an instance of Display, which automatically initializes the JPanel with the overridden paint(g) method, thus the new Operator.
As the constructor of a JPanel returns a JPanel, the constructor of Display returns a type of JPanel as well, which contains the red circle. This JPanel needs to be added with the add method to your original JFrame.
Im trying to add a JScrollpane to my JPanel. The problem is that the scrollpane doesn't recognize that my drawing is outside the frame. So how do I add the JScrollpane correctly?
Main class:
public MainFrame() extends JFrame{
public MainFrame() {
Container container = getContentPane();
container(new BorderLayout());
container.add(new JScrollPane(new Drawing()));
setSize(1280,720);
setVisible(true);
}
Drawing class:
public class Drawing() extends JPanel {
#Override
protected void paintComponent(Graphics g) {
g.drawLine(10, 100, 30000, 10);
}
}
There are a couple of errors in your code, let's step through each of them:
You're extending JFrame, and you should avoid it, see: Extends JFrame vs. creating it inside the program for more information about it. You're actually not changing its behavior so it's not needed to extend it.
For your JScrollPane to show the whole line, you need to change your window's size to be the same size of your line (as shown in this answer by #MadProgrammer).
Related to point 2, avoid the use of setSize(...) and instead override getPreferredSize(): See Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? for more information
You forgot to call super.paintComponent(...) method in your paintComponent() method.
Related to points 2, 3, you need to call pack() so Swing calculates the best preferred size for your component.
See this example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class LongDraw {
private JFrame frame;
private Drawing drawing;
public static void main(String[] args) {
SwingUtilities.invokeLater(new LongDraw()::createAndShowGui);
}
private void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
drawing = new Drawing();
JScrollPane scroll = new JScrollPane(drawing);
frame.add(scroll);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class Drawing extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawLine(10, 100, 3000, 10);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(3000, 500);
}
}
}
Which produces something similar to this:
Why does this not work? It shows me the GUI but not the paint. How would I change this into two classes?
import java.awt.Graphics;
import javax.swing.JFrame;
public class runpaintgui extends JFrame{
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setSize(5000,2000);
frame.setResizable(false);
frame.setTitle("game");
frame.setVisible(true);
}
public void paint(Graphics g){
super.paint(g);
g.drawString("adsf",40,45);
g.draw3DRect(50, 30, 600, 700, true);
repaint();
}
}
You are creating a generic JFrame in this line:
JFrame frame = new JFrame();
What you want to probably do is:
JFrame frame = new runpaintgui();
Then your paint() method will be called.
You have to instantiate your class and not the JFrame class.
change:
JFrame frame = new JFrame();
to
runpaintgui frame = new runpaintgui();
Then your paint() method will be called.
And do not call repaint() in paint. Because repaint() calls paint.
I'm trying to find what is wrong with this short code. I can't print the String TEXT in my JFrame using drawString() method. Please Help . Only a plain white screen will appear if you run the program .
Code:
import javax.swing.*;
import java.awt.*;
public class sample extends JFrame
{
private JPanel panel;
public sample()
{
setSize(500,500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
panel =new JPanel();
Container mainP= getContentPane();
mainP.add(panel);
panel.setBounds(0,0,500,500);
panel.setBackground(Color.WHITE);
}
public void paintComponent(Graphics g)
{
Graphics2D eg = (Graphics2D)g;
eg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
eg.setColor(Color.BLACK);
eg.drawString("TEXT", 40, 120);
}
public static void main(String args[])
{
new sample();
}
}
JFrame has no paintComponent method. So you aren't override anything, and not painting will be done.
On that note JPanel does have a paintComponent method, and you should be painting on a JComponent or JPanel, which do have the method. You don't want to paint on top-level containers like JFrame. (if you really need to know though, the correct method to override is paint for JFrame).
That being said, you should also call super.paintComponent inside the paintComponent method so you don't break the paint chain and leave paint artifacts.
Side Notes
As good practice, make use of the #Override annotation, so you know you are correctly overriding a method. You would've seen that paintComponent doesn't override one of JFrames methods.
setVisible(true) after add your components.
panel.setBounds(0,0,500,500); will do absolutely nothing, since the JFrame has a default BorderLayout
Follow Java naming convention and use capital letters for class names.
Run Swing apps from the Event Dispatch Thread. See more at Initial Threads
FINAL
import javax.swing.*;
import java.awt.*;
public class Sample extends JFrame {
private JPanel panel;
public Sample() {
setSize(500, 500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D eg = (Graphics2D) g;
eg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
eg.setColor(Color.BLACK);
eg.drawString("TEXT", 40, 120);
}
};
Container mainP = getContentPane();
mainP.add(panel);
panel.setBackground(Color.WHITE);
setVisible(true);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new Sample();
}
});
}
}
I have a JFrame created with GUI builder of Netbeans, which contains a JPanel only. I have created a method getPanel for getting a reference to this JPanel:
public class ShowDrawings extends JFrame {
public ShowDrawings() {
initComponents();
}
public JPanel getPanel(){
return panel;
}
private JPanel panel;
}
In my main function I am doing:
public class Main {
public static void main(String[] args){
ShowDrawings sd = new ShowDrawings();
sd.setSize(800, 600);
Graphics g = sd.getPanel().getGraphics();
g.setColor(Color.BLACK);
g.drawOval(400, 300, 50, 50);
sd.getPanel().paint(g);
sd.repaint();
sd.setVisible(true);
}
}
But it does not draw anything. Please help me.
I have looked some related questions but they are all suggesting extending JPanel and overriding its paint method. But I did not want to do that way.
Thanks.
I have looked some related questions but they are all suggesting
extending JPanel and overriding its paint method. But I did not want
to do that way
You should not override JPanel paint() method, rather paintComponent(..). This is best practice and should be done if you want code that will not produce anomalies. Also doing it in your current approach (as you have seen) makes creating persistent drawings a lot harder as they are wiped away on repaint()
Rather extend JPanel and override paintComponent(Graphics g) not forgetting to call super.paintComponent(g) as first call in overridden paintComponent(..) method. Also dont forget to override getPreferredSize() of JPanel so that we can return correct dimensions and pack() may be called on JFrame (+1 to #mKorbels comment):
Here is some example code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public Test() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void initComponents() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel testPanel = new JPanel() {
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
Graphics2D g2d = (Graphics2D) grphcs;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.GREEN);
//g2d.drawOval(10,10,100,100);//I like fill :P
g2d.fillOval(10,10,100,100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
};
frame.add(testPanel);
frame.pack();
frame.setVisible(true);
}
}
The first time you repaint() your ShowDrawings sd frame anything you've painted like this (sd.getPanel().getGraphics().drawOval(...)) would be erased by the original JPanel#paintComponent() method.
As Andrew Thompson has written:
Do not use Component.getGraphics(). Instead, subclass and override the paint() (AWT), or paintComponent() (Swing) method.
Component.getGraphics() simply can't work. Java uses a callback mechanism for drawing graphics. You are not supposed to "push" graphics information into a component using getGraphics(). Instead you are supposed to wait until Java calls your paint()/paintComponent() method. At that moment you are supposed to provide the Component with the drawings you would like to do.
If you're just checking/debugging something you could even do something like this:
class Test {
private JPanel panel = new JPanel() {
public void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.drawOval(400, 300, 50, 50);
}
};
}