applet中的双缓冲如何工作?

时间:2015-01-19 02:32:05

标签: java

我正在使用youtube上的视频教程编写Java代码来制作Java游戏applet。但是,教师并没有真正解释applet的更新方法如何在他调用时进行双缓冲。


    import java.awt.*;
    import java.applet.Applet;
    public class Game extends Applet implements Runnable {

    private Image i;
    private Graphics g2;
    private int x, y, dx = 1, dy = 1, radius = 10;

    ...
    public void update(Graphics g) {
                if ( i == null ) {
                    i = createImage(getHeight(), getHeight());
                }
                g2 = i.getGraphics();

                g2.setColor(getBackground());
                g2.fillRect(0, 0, getWidth(), getHeight());

                g2.setColor(getForeground());
                paint(g2);
                g.drawImage(i, 0, 0, null);
            }


    public void paint(Graphics g) 
            {
                x+= dx;
                y+= dy;
                g.setColor(Color.RED);
                g.fillOval(  x, getHeight() - y, radius * 4, radius * 4);
                g.setColor(Color.BLUE);
                g.fillOval( getWidth() - x - radius, y, radius * 4, radius * 4);
                g.setColor(Color.GREEN);
                g.fillOval( x, y, radius * 4, radius * 4);
                g.setColor(Color.YELLOW);
                g.fillOval( getWidth() - x , getHeight() - y , radius * 4, radius * 4);     
            }

这里是如何消除闪烁的?拥有Image对象有什么用?有另一个Graphics对象有什么用,为什么不使用参数Graphics?

1 个答案:

答案 0 :(得分:4)

双缓冲的一般想法是绘图很慢,如果你有很多东西要绘制,用户会以闪烁的形式注意到这一点。相反,您将所有绘图都设置为屏幕外图像(缓冲区)。然后,当您准备好时,您交换屏幕外缓冲区,以便它现在在屏幕上绘图。这种交换很快发生,因为它通常只是更新指针。

用户不再看到闪烁,因为所有绘图工作都在屏幕外完成。

您发布的代码是双缓冲的变体。所有绘图工作都在屏幕外完成到Image对象i。绘图完成后,图像对象将被复制到update方法的最后一行中的组件。

我说变种是因为上面的代码没有交换缓冲区。而是将屏幕外缓冲区i复制到屏幕缓冲区Graphics。它仍然消除了闪烁,因为所有渲染工作都在屏幕外完成。复制图像仍然非常快。

第二个g2对象存在,因为在绘制时应始终使用组件提供的对象。因此,上面的代码询问Image对象的Graphics对象。但是,没有真正的理由将update存储为成员变量,您每次只能在{{1}}中请求它。