Porthos3
Porthos3

Reputation: 401

Why can't I paint onto my JPanel using Graphics?

I keep running into this problem when I try to paint to my extended version of a JPanel. Every time, I eventually find a way to get it to work. But I want to know exactly why it is that painting to a JPanel in this way doesn't work?

public class MyPanel extends JPanel {

public MyPanel(){
    init();
}

public void init(){
    JFrame frame = new JFrame("");
    frame.add(this);
    this.setPreferredSize(new Dimension(100,100));
    this.setBackground(Color.RED);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);

    Graphics g = this.getGraphics();
    g.setColor(Color.BLUE);
    g.fillRect(0, 0, 50, 50);
}

public static void main(String[] args) {
    new MyPanel();
}

}

When I run this code, I see the red background I would expect from setBackground(Color.RED), but I don't see the blue rectangle that I painted using the Graphics object. It doesn't show up, even if I call repaint() on the last line in init().

What is wrong with this code, so I can avoid it in the future?

Upvotes: 0

Views: 739

Answers (2)

BackSlash
BackSlash

Reputation: 22233

Why can't I paint onto my JPanel using Graphics?

Because this is not the right way to do it. You should override the paintComponent method:

public class MyPanel extends JPanel {

    public MyPanel(){
        init();
    }

    public void init(){
        JFrame frame = new JFrame("");
        frame.add(this);
        this.setPreferredSize(new Dimension(100,100));
        this.setBackground(Color.RED);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

    }

    public static void main(String[] args) {
        new MyPanel();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLUE);
        g.fillRect(0, 0, 50, 50);
    }
}

If you don't do so, your drawing will be visible for just one moment, and then it will disappear. This way, whenever you call the repaint method (or whenever the application gets repainted itself), that method will be called and your rectangle will be filled.

Upvotes: 3

MadProgrammer
MadProgrammer

Reputation: 347184

Custom painting in Swing is typically done by overriding the paintComponent Method of classes that extend from JComponent

See Performin a Custom Painting for details

Basically, the problem is, painting in Swing is destructive process. Each time a paint cycle occurs, you are expected to clean and regenerate the output. getGraphics is unreliable. It can return null and anything you paint using it, will be over painted on the next paint cycle

Upvotes: 2

Related Questions