2

I have been practicing with java's swing features recently, and in one of my classes that extends the class JPanel, I have overriden the method paintComponent() so that it will paint my BufferedImage onto the JPanel. I also have a method on it to move around. Before this issue, I have had a problem that shows the process of moving as it repaints too quickly. So, I created a boolean variable called available which is set to false when the image is still in the moving process. But, now I see that the screen is taking away the entire image and putting it back, causing it to blink. Here is my basic pseudocode:

class A extends JPanel{
    BufferedImage canvas;
    public A(){
        //create image here
    }
    public move(){
        available = false;
        //move things around in here
        available = true;
    }
    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        if(available){
            g.drawImage(this.canvas, 0, 0, null);
        }
        g.dispose();
    }
}
class B{
    public static void main(String[] args){
        //construct the class A JPanel
        while(some_variable){
            class_A_JPanel.repaint();
        }
    }
}
pasghetti
  • 57
  • 7
  • 1
    Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This is not a code dump, but an example of what you are doing which highlights the problem you are having. This will result in less confusion and better responses – MadProgrammer Apr 29 '15 at 01:02
  • Painting is a destructive process, each time `paintComponent` is called, you are expected to update the entire state of the component. Also, Swing uses a passive rendering approaching, meaning a paint request could occur at any time for any reason, may of which you don't control. This "seems" to be systemic thread race issue, but it's impossible to know from the out of context code snippet – MadProgrammer Apr 29 '15 at 01:03
  • Sorry, but I don't think I can simulate my code with a short enough runnable example. There are too many classes involved. But, I can tell you that in my code there is a loop that repaints this JPanel. There may be something in that causing the problem, but I am not sure. I will edit my answer to include that. – pasghetti Apr 29 '15 at 01:22
  • The I "suggest" creating two `BufferedImage` images, one which is painted to the screen and one which you paint to off screen. When you call `move`, paint to the off screen buffer and when you are done, switch the references, so the "off screen" becomes the "on screen" and visa versa. Always paint the on-screen buffer in the `paintComponent` method. You might need to make these `volatile` so that different threads are working with the correct reference – MadProgrammer Apr 29 '15 at 01:25
  • If you were using a Canvas I would suggest using a BufferStrategy. – StrongJoshua Apr 29 '15 at 01:42
  • MadProgrammer, I tried your approach just now, and I believed it worked. Thank you. – pasghetti Apr 29 '15 at 02:07
  • try to remove g.dispose(); – eckes Apr 29 '15 at 02:41
  • What would removing g.dispose() do? – pasghetti Apr 29 '15 at 03:15
  • Also, MadProgrammer, can you put the answer 5 comments up as an answer below? I will mark it as accepted. – pasghetti Apr 29 '15 at 03:18

1 Answers1

1

This is very old topic which is fixed in modern Java. But you prefer old way then use old techniques. For example Double Buffering

Izold Tytykalo
  • 719
  • 1
  • 5
  • 15