AWT Canvas BufferStrategy and resize flickering

1.4k views Asked by At

I am trying to make a simple game using Java2D for maximum compatibility. It is working great under Java 8 on Mac OS X Yosemite, but it is not as fluid when I try the same code under Windows 7. The canvas flickers when the JFrame is being resized and this is really ugly.

My application uses an AWT Canvas with BufferStrategy and works like this. Another thread calls repaint when something moves in the environment. But for the window resizing handling, my strategy is the following:

public class TestCanvas
{
    private static final Color[] colors = new Color[]{Color.black, Color.darkGray, Color.gray, Color.lightGray, Color.blue.darker().darker(), Color.blue, Color.blue.brighter().brighter(), Color.white};

    public static void main(String[] args)
    {
        JFrame frame = new JFrame("Test Canvas");
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        Canvas canvas = new Canvas()
        {
            @Override
            public void paint(Graphics g)
            {
                BufferStrategy bufferStrategy = getBufferStrategy();
                g = bufferStrategy.getDrawGraphics();
                paint100Circles(g);
                g.dispose();
                bufferStrategy.show();
            }

            @Override
            public void update(Graphics g)
            {
                paint(g);
            }

            @Override
            public void repaint()
            {
                paint(null);
            }
        };
        contentPane.add(canvas, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(1000, 1000);
        frame.setVisible(true);
        canvas.createBufferStrategy(2);
    }

    public static void paint100Circles(Graphics g)
    {
        Random random = new Random(0);
        for (int i = 0; i < 100; i++)
        {
            int x = Math.abs(random.nextInt()) % 1000;
            int y = Math.abs(random.nextInt()) % 1000 + (Math.abs(random.nextInt() % 1000) / 25);
            int size = 50 + Math.abs(random.nextInt()) % 50;
            g.setColor(colors[Math.abs(random.nextInt()) % colors.length]);
            g.fillOval(x, y, size, size);
        }
    }
}

Maybe I am not using the BufferStrategy in the right way?

1

There are 1 answers

5
Joeblade On

I use createBufferStrategy(3) but 2 should be ok too.

in this answer you are basically encouraged to use paintComponent, not paint(). to quote:

"The problem here is paint does a number of important jobs, calling paintComponent is just one of them."

You might want to try switching to paintComponent. Everything else you're doing looks pretty much ok.

However having said that, in my own code I don't call paint() or paintComponent() at all. Instead, I write to the bufferStrategy whenever I can (render() loop runs as many times as it can)

I think when you use bufferStrategy you write to the buffer outside of paint() and during paint just write the buffer to screen. like it says in this answer, though it gained no points it might still have valid hints.

So I think either use paintComponent and do your painting right there (you can still set a double buffering strategy I think, but draw to your graphics) or write to the buffer outside of paintComponent/paint and let the component draw the buffer when it wants.