Java双缓冲技术

5

我正在开发一个项目,已经尽可能多地阅读了有关Java双缓冲的信息。我想做的是向我的JFrame添加一个包含双缓冲表面以进行绘制的组件或面板等。如果可能的话,我想使用硬件加速,否则使用常规软件渲染器。到目前为止,我的代码如下:

  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();
    }
}

我创建了一个抽象的游戏类和一个游戏循环,调用Update和Draw。现在,如果您看到我的注释,那就是我主要关注的地方。有没有一种方法可以一次获取图形,而不是通过repaint和paintComponent进行每次重绘然后再分配变量?此外,默认情况下是否启用硬件加速?如果没有,我应该怎么做才能让它启用硬件加速?

相关:http://stackoverflow.com/questions/2067255/bufferstrategy-vs-diy-double-buffering-in-jframe - finnw
2个回答

9
如果您想更好地控制窗口更新的时间并利用硬件翻页(如果有),您可以使用BufferStrategy类。
然后,您的Draw方法将如下所示:
@Override
protected void Draw() {
    BufferStrategy bs = getBufferStrategy();
    Graphics g = bs.getDrawGraphics(); // acquire the graphics

    // draw stuff here

    bs.show(); // swap buffers
}

这种方法的缺点是与事件驱动渲染不太兼容。通常需要选择其中之一。此外,getBufferStrategy仅在CanvasWindow中实现,因此与Swing组件不兼容。
教程可以在这里, 这里这里找到。

2
不要扩展JPanel,应该扩展JComponent。它们基本相同且代码干扰较少。此外,您只需在paintComponent中编写绘图代码。如果需要手动刷新组件,则应使用component.redraw()

3
Swing默认启用了双缓冲。参见:http://java.sun.com/products/jfc/tsc/articles/painting/index.html#db - camickr
@camickr,您建议即使是游戏也使用默认的吗?例如,使用标签来绘制通常需要自己渲染的对象的图像。因此,您可以更改标签位置而不是更改位置以绘制图像。您有关于这种方法的文章吗? - Boro
@Boro,我在上面的评论中并没有真正推荐任何东西。我只是指出您不需要在Swing中显式启用双缓冲。我不知道使用JLabel还是直接绘制图标更好。从理论上讲,直接绘制图标应该更有效率,因为JLabel绘制代码必须首先检查是否有要绘制的文本,并设置标签内图标的位置等。但真正的瓶颈是图形绘制代码还是标签绘制代码中的这些额外语句呢? - camickr
@Boro,更改位置更容易。Swing将确定需要重新绘制的内容(即,您需要重新绘制标签之前的背景,然后再绘制它现在所在的位置)。如果您自己进行绘画,则需要自行管理此过程。如果您的游戏需要重新绘制整个屏幕,则可能不是问题。但是,如果您只是在这里和那里移动几个图标,让Swing管理重绘可能更容易。我从未编写过游戏,因此没有任何实际经验。 - camickr
@camickr非常感谢您的回答。我自己写了一些玩具项目游戏,使用了两种方法。通常取决于游戏的内容。一个简单的按钮点击器特别适合使用标签,因为它处理鼠标点击等操作。当我做一些实时相关的工作时,我会选择主动渲染。但是,由于您在几篇帖子中都提到了标签方法,如果我没记错的话,我想知道您是否可以提供一些关于这种方法在游戏开发上的阅读材料。再次感谢。 - Boro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接