Mohammed Aouf Zouag
Mohammed Aouf Zouag

Reputation: 17142

Why is the paintComponent method called twice?

I'm working on an app where I draw everything pixel by pixel. During the process, I noticed that the paintComponent() method of a certain JPanel is called twice. So I created the following MCVE to figure out whether it has something to do with the other components being drawn to the screen, or if it's just a standalone issue:

App.java

public class App {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new MainFrame("Paint test"));
    }
}

MainFrame.java

public class MainFrame extends JFrame {
    private Board mBoard;

    public MainFrame(String title) {
        super(title);

        setMinimumSize(new Dimension(400, 400));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout());

        mBoard = new Board();
        add(mBoard, BorderLayout.CENTER);

        setVisible(true);
    }
}

Board.java

public class Board extends JPanel {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        System.out.println("CALLED");
    }
}

But the console log shows "CALLED" twice.

I'm specifically interested in paintComponent() since it's the method where all of the app's magic works, so I need to control each draw cycle.

What are the reasons behind this double call to paintComponent() ?

Is there another way I could do my drawings some other way once ? (I mean, not in paintComponent(), if it would be called twice no matter what)

Upvotes: 3

Views: 2048

Answers (2)

Andrew Thompson
Andrew Thompson

Reputation: 168845

Why is the paintComponent method called twice?

Because it is called whenever the plug-in determines it is needed.

I need to control that behavior.

Better to use an approach that works, rather than chase an end that cannot be achieved.

The logical approach to this conundrum though, is to instead draw everything to a BufferedImage that is displayed in (an ImageIcon that is displayed in) a JLabel. Then no matter how many times the repaint() method of the label is called, the app. still only needs to generate the pixels once.

Examples

  1. Draw in an image inside panel

    enter image description here

  2. Multiple calls of paintComponent()

    enter image description here

  3. Drawing the Cannabis Curve

    enter image description here

Upvotes: 5

user1803551
user1803551

Reputation: 13427

After reading the short discussion in the comments I have a suggestion. Prepare the Shape object and save it as a resource. This will save the runtime calculations. When the program launches, load the file in a separate thread (parallel to loading the GUI) and then just paint that object. Doing just the painting shouldn't be expensive so even if it's called several times there shouldn't be a problem.

Upvotes: 0

Related Questions