7

Here is simple example of drawing an oval.

public class SwingPainter extends JFrame{
    public SwingPainter() {
        super("Swing Painter");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        getContentPane().add(new MySwingComponent());

        setSize(200, 200);
        setVisible(true);
    }

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

    class MySwingComponent extends JComponent {

         public void paintComponent(Graphics g) {
            System.out.println("paintComponent");
            super.paintComponent(g);
            g.setColor(Color.red);
            g.fillOval(10, 10, 50, 50);
        }

        @Override
        protected void paintBorder(Graphics g) {
            System.out.println("Paint border");
            super.paintBorder(g);
        }

        @Override
        protected void paintChildren(Graphics g) {
            System.out.println("Paint children");
            super.paintChildren(g);
        }
    }
}

But in debug mode or adding some info to console before drawing (as in example), you can see that swing draws components twice.

paintComponent

Paint border

Paint children

paintComponent

Paint border

Paint children

I cannot understand why it happens, but I think it can affect performance in a difficult GUI.

Community
  • 1
  • 1
Dragon
  • 2,379
  • 10
  • 40
  • 61

3 Answers3

9

The article Painting in AWT and Swing: Additional Paint Properties: Opacity suggests why: "The opaque property allows Swing's paint system to detect whether a repaint request on a particular component will require the additional repainting of underlying ancestors or not." Because you extend JComponent, the opaque property is false by default, and optimization is not possible. Set the property true to see the difference, as well as the artifact from not honoring the property. Related examples may be found here and here.

Community
  • 1
  • 1
trashgod
  • 196,350
  • 25
  • 213
  • 918
  • Yes, you're right. It is because of opaque. When I set it to true, only 3 records are in console output. I need to investigate opaque work more thoroughly :) – Dragon Aug 15 '12 at 10:46
2

I agree with Konstantin, what you need to remember, the repaint manager is responding to any number of requests when the application starts, this typically includes the initial paint request when the window is shown and resized (there's two).

Try this. Wait till the application is running and resize the window. I'm sure you'll get more then a couple of repaint requests ;)

MadProgrammer
  • 323,026
  • 21
  • 204
  • 329
2

This works fine to me. In fact, even in debug mode the output was:

paintComponent
Paint border
Paint children

Please, bear in mind that in AWT and Swing components there are many methods (paint, paintBorder, paintChildren, paintComponent, repaint, and others) that are called via call-back, whenever the GUI engine finds suitable. That may vary from JVM to JVM or even from different execution sessions. They can also be triggered from the interaction to your program (if you minimize/maximize, for example). Or they may not, at all.

Filipe Fedalto
  • 2,402
  • 1
  • 15
  • 20