【问题标题】:Java Double BufferingJava 双缓冲
【发布时间】:2011-08-20 22:46:03
【问题描述】:

我正在做一个项目,我已经尽可能多地阅读了有关 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 的游戏循环。现在,如果你看到我的 cmets,那是我主要关心的领域。有没有办法获得一次图形,而不是通过重绘和paintComponent,然后在每次重绘时分配一个变量?另外,这个硬件是默认加速的吗?如果不是,我应该怎么做才能使其硬件加速?

【问题讨论】:

标签: java swing awt doublebuffered


【解决方案1】:

如果您想更好地控制窗口何时更新并利用硬件页面翻转(如果可用),您可以使用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 组件不兼容。

教程可以在hereherehere找到。

【讨论】:

    【解决方案2】:

    不要扩展JPanel。扩展JComponent。它几乎是相同的并且具有更少的干扰代码。此外,您只能在paintComponent 中执行绘图代码。如果需要手动刷新组件,可以使用component.redraw()。

    【讨论】:

    • Swing 中默认启用双缓冲。见:java.sun.com/products/jfc/tsc/articles/painting/index.html#db
    • @camickr 所以你会建议使用默认的游戏吗?并且,例如,使用标签来绘制您通常会自己渲染的对象的图像。因此,您可以更改标签位置,而不是更改绘制图像的位置?你有关于这种方法的文章吗?
    • @Boro,我上面的评论并没有真正推荐任何东西。我只是指出您不需要在 Swing 中显式打开双缓冲。不知道是用JLabel还是直接画Icon比较好。理论上直接绘制Icon应该更高效,因为JLabel绘制代码首先要检查是否有文本要绘制并设置Icon在标签内的位置等。但是真正的瓶颈是Graphics绘制代码还是这些额外的语句在标签绘画代码中?
    • @Boro,更改位置更容易。 Swing 将确定需要重新绘制的内容(即,在绘制现在的位置之前,您需要重新绘制标签所在位置的背景)。如果您自己绘画,则需要自己进行管理。如果您的游戏无论如何都需要重新绘制整个屏幕,那可能不是问题。但是,如果您只是在这里和那里移动几个图标,让 Swing 管理重绘可能会更容易。我从来没有写过游戏,我没有任何现实世界的经验。
    • @camickr 非常感谢您的回答。我自己编写了一些玩具项目游戏,并且我一直在使用这两种方法。一般来说,这取决于游戏的内容。一个简单的按钮点击器非常适合带有标签,尤其是处理鼠标点击等。当我做一些实时相关的时候,我会去进行主动渲染。但是,既然你在几篇文章中提到了带有标签的方法,如果我没记错的话,我想知道你是否可以在游戏开发的背景下提供一些关于这种方法的阅读。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2012-03-22
    • 2011-01-05
    • 2013-08-07
    • 2011-02-20
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多