technik3k
technik3k

Reputation: 158

Can't stop flickering on JPanel

I have class that creates a new thread.

`

public ScreenG(JPanel PanelR)
{
    Panel = PanelR;
    RenderImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
    FPS = 25;
    Hide = false;

    (new Thread() 
    {
        public void run() 
        {   
              while(true)
              {
                  if(Hide == false)
                  {
                    Timer = System.currentTimeMillis() + (1000/FPS);

                    if(!DrawRendering)
                    {
                        Graphics g = Panel.getGraphics();
                        g.drawImage(RenderImage, 0, 0, null);
                    }

                    DrawRendering = false;

                    while(System.currentTimeMillis() <= Timer) try { Thread.sleep(1); } catch (InterruptedException e) {Thread.currentThread().interrupt();}
                  }
              }
        }
    }).start();
}

public void draw(BufferedImage ImageR)
{
    DrawRendering = true;
    RenderImage = ImageR;
    Graphics g = Panel.getGraphics();
    g.drawImage(RenderImage, 0, 0, null);
}`

In my main I create a new instance of ScreenG. This will start a new thread that draws a bufferedImage onto a JPanel with a consistent FPS. In the main I would then call draw with the image that I created. Sometimes it works but sometimes the image on the panel flickers. I try variations like the draw function taking over the drawing. Non of them work. I could only REDUCE the flickering.

Upvotes: 1

Views: 2419

Answers (3)

technik3k
technik3k

Reputation: 158

Thank you for the answers. I read Oracle tutorial that you recommended and get my paintComponent() function working correctly on the main thread. To do that I am calling JPanel().repaint() from the draw() function. I will learn about using BufferStrategy next.

Upvotes: 0

Emz
Emz

Reputation: 1280

The flickering can be because the rendering isn't fast enough from an update.

Now I do recommend you use Swings paintComponent (Graphics g) when rendering its components. That being said. To solve the flickering for you add a BufferStrategy in your JFrame

Without that code avaible I can only provide a general solution.

JFrame jframe = new JFrame ();

...

BufferStrategy bufferstrategy = jframe.getBufferStrategy ();

if (bufferstrategy == null) {
    jframe.createBufferStrategy(3);
    return;
}

g.dispose();
bufferstrategy.show();

To read more about BufferStrategy I recommend a read over at the documentation.

Small Note

There is no reason in your code to either store JPanel PanelR or BufferedImage ImageR. You can instead directly invoke methods directly on PanelR resp. ImageR.

Upvotes: 0

Durandal
Durandal

Reputation: 20069

Not possible by design. Swing does not synchronize to the bitmap raster DMA that's actually sending the screen data to your monitor, so it always possible that the screen buffer is read by the DMA while you're busy rendering to it (possible exception is Fullscreen mode).

To at least minimize flickering follow the recommended method of custom Swing painting: https://docs.oracle.com/javase/tutorial/uiswing/painting/

You can easily trigger periodic repaints on the EDT using a Swing timer, or SwingUtilities.invokeAndWait/invokeLater from another thread (whatever works best in your design).

Upvotes: 2

Related Questions