views:

535

answers:

4

I'm drawing shapes inside this JPanel, which is also inside another main JPanel. At repaint() it only draws the shapes for one millisecond and then they disappear. They don't stay painted, why? my paintComponent method is something like this

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

    for (int i = 0; i < reportElements.size(); i++) {
        this.reportElements.get(i).display((Graphics2D) pageComponents.get(i).getGraphics());

    }
}

When the parent is a JEditorPane with setEditable() enabled, it works and we can see the shapes but when it's a JPanel, after a millisecond all I see is empty panels.

A: 

It might be that paintChildren or paintBorder overdraws whatever you've drawn in your method. Perhaps try overriding paint instead. There you have full control over what will be painted on the component, and you can decide yourself whether to further call paintComponent, paintChildren or paintBorder at all.

Joonas Pulakka
i think i tried that and it didn't work. thanks
Halo
+2  A: 

you should paint to the Graphics object of the JPanel for it to be permanent... In your example, that is the Graphics g...

ultrajohn
i'll try it right away
Halo
but wait a sec. in this case what happens to those pageComponents, the small JPanels? The parent panel is not gonna draw the shapes on them is it? then are they useless now?
Halo
+1  A: 

ultrajohn is dead on. You need to use the Graphics you have been passed. Read on for the why...

Java 1.6 introduced the RepaintManager that supports the optimizing of repaint requests. It has some subtle effects on painting.

In this case, you're working with multiple Graphics2D objects: the g passed into paintComponent and the value returned by the getGraphics call.

The repaint manager has handed you g on which to paint. Note: this does not paint on the screen, but on a temporary buffer (assuming the default double buffering).

In the paintComponent call you are painting to the graphics obtained from getGraphics of the various components. This is bypassing the repaint manager and painting directly to the unbuffered display.

When paintChildren returns, the RepaintManager kicks in to handle updating the double buffer. It paints the blank temporary buffer over the displayed buffer, effectively erasing what was painted through the graphics object obtained from getGraphics

Devon_C_Miller
thanks for the explanation man i'll try it after dinner.
Halo
+2  A: 

in this case what happens to those pageComponents, the small JPanels? The parent panel is not gonna draw the shapes on them is it?

I'm not sure I undertand your comment. Your main panel should contain child panels. The child panels should be added to the main panel using a layout manager. Then when Swing decides to repaint the main panel, it will also repaint all the child panels and in turn the child panels will repaint there shapes.

For what its worth Custom Painting Approaches has a working example of drawing shapes on a panel.

camickr
what I mean is I'd like the shapes to not be on the main panel but the children, so that when I change one of those small JPanels's coordinates the drawing would also change position, or when I remove one of the JPanels, the drawing would also disintegrate(BG-SoA).
Halo
Well, that is exactly what I described, the paintComponent() method of each child panel is customized. Then when you add the child panel to the parent the painting of the child is done automatically.
camickr
I understand, then to customize their paint I guess I need to create a seperate class for the child panel as well? Cause I just created objects of JPanel before. no wait wouldn't that lead to the same problem in the first place?
Halo
well it worked. now, eea which answer should I tick :) everyone gave good feedback thanks.
Halo