Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Double Buffering

I'm working on a project and I've read up as much as I can on double buffering in java. What I want to do is add a component or panel or something to my JFrame that contains the double buffered surface to draw to. I want to use hardware acceleration if possible, otherwise use regular software renderer. My code looks like this so far:

  public class JFrameGame extends Game {

    protected final JFrame frame;
    protected final GamePanel panel;
    protected Graphics2D g2;

    public class GamePanel extends JPanel {

        public GamePanel() {
            super(true);
        }

        @Override
        public void paintComponent(Graphics g) {
            g2 = (Graphics2D)g;
            g2.clearRect(0, 0, getWidth(), getHeight());
        }
    }

    public JFrameGame() {
        super();
        gameLoop = new FixedGameLoop();

        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        panel = new GamePanel();
        panel.setIgnoreRepaint(true);
        frame.add(panel);

        panel.setVisible(true);
        frame.setVisible(true);
    }

    @Override
    protected void Draw() {
        panel.repaint(); // aquire the graphics - can I acquire the graphics another way?
        super.Draw(); // draw components

        // draw stuff here

        // is the buffer automatically swapped?
    }


    @Override
    public void run() {
        super.run();
    }
}

I created an abstract game class and a game loop that calls Update and Draw. Now, if you see my comments, that's my main area of concern. Is there a way to get the graphics once instead of going through repaint and paintComponent and then assigning a variable every redraw? Also, is this hardware accelerated by default? If not what should I do to make it hardware accelerated?

like image 485
Caleb Jares Avatar asked May 07 '11 23:05

Caleb Jares


2 Answers

If you want more control over when the window is updated and to take advantage of hardware page flipping (if available), you can use the BufferStrategy class.

Your Draw method would then look something like this:

@Override
protected void Draw() {
    BufferStrategy bs = getBufferStrategy();
    Graphics g = bs.getDrawGraphics(); // acquire the graphics

    // draw stuff here

    bs.show(); // swap buffers
}

The downside is that this approach does not mix well with event-driven rendering. You generally have to choose one or the other. Also getBufferStrategy is implemented only in Canvas and Window making it incompatible with Swing components.

Tutorials can be found here, here and here.

like image 157
finnw Avatar answered Oct 31 '22 10:10

finnw


Don't extend JPanel. Extend JComponent. It's virtually the same and has less interfering code. Also, you'd do the drawing code in paintComponent only. If you need to manually refresh the component, you'd use component.redraw().

like image 44
Chris Dennett Avatar answered Oct 31 '22 12:10

Chris Dennett