Java 小程序中的双缓冲是如何工作的?

Java 小程序中的双缓冲是如何工作的?,java,Java,我在youtube上的一个视频教程中编写了这段Java代码,内容是制作Java游戏小程序。然而,讲师并没有真正解释小程序的更新方法如何在调用时进行双缓冲 import java.awt.*; import java.applet.Applet; public class Game extends Applet implements Runnable { private Image i; private Graphics g2; private int x

我在youtube上的一个视频教程中编写了这段Java代码,内容是制作Java游戏小程序。然而,讲师并没有真正解释小程序的更新方法如何在调用时进行双缓冲

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); } 导入java.awt.*; 导入java.applet.applet; 公共类游戏扩展小程序实现可运行{ 私人形象一; 专用图形g2; 私有整数x,y,dx=1,dy=1,半径=10; ... 公共空间更新(图g){ 如果(i==null){ i=createImage(getHeight(),getHeight()); } g2=i.getGraphics(); g2.setColor(getBackground()); g2.fillRect(0,0,getWidth(),getHeight()); g2.setColor(get前台()); 油漆(g2); g、 drawImage(i,0,0,null); } 公共空间涂料(图g) { x+=dx; y+=dy; g、 setColor(Color.RED); g、 圆角(x,getHeight()-y,半径*4,半径*4); g、 setColor(Color.BLUE); g、 圆角(getWidth()-x-半径,y,半径*4,半径*4); g、 setColor(Color.GREEN); g、 圆角(x,y,半径*4,半径*4); g、 setColor(颜色为黄色); g、 圆角椭圆(getWidth()-x,getHeight()-y,半径*4,半径*4); }
这里是如何消除闪烁的?拥有一个图像对象有什么用?拥有另一个图形对象有什么用,为什么不使用参数图形?

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

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

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

我之所以说variant,是因为上面的代码没有交换缓冲区。相反,您正在将屏幕外的缓冲区
I
复制到屏幕上的缓冲区。它仍然可以消除闪烁,因为所有渲染工作都是在屏幕外完成的。复制图像仍然非常快


第二个
Graphics
对象就在那里,因为您应该在绘图时始终使用组件提供的对象。因此,上面的代码向图像对象请求其图形对象。但是,没有真正的理由将
g2
存储为成员变量,您只需在
update
中每次请求它双缓冲的概念是绘图速度慢,如果你有很多东西要画,用户会以闪烁的形式注意到这一点。相反,你所有的绘图都是在屏幕外的图像(缓冲区)上进行的。然后,当您准备好时,交换屏幕外缓冲区,使其现在在屏幕上绘制。这种交换发生得非常快,因为它通常只是更新指针

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

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

我之所以说variant,是因为上面的代码没有交换缓冲区。相反,您正在将屏幕外的缓冲区
I
复制到屏幕上的缓冲区。它仍然可以消除闪烁,因为所有渲染工作都是在屏幕外完成的。复制图像仍然非常快


第二个
Graphics
对象就在那里,因为您应该在绘图时始终使用组件提供的对象。因此,上面的代码向图像对象请求其图形对象。但是,没有真正的理由将
g2
存储为成员变量,您只需在
update
中每次请求它双缓冲的概念是绘图速度慢,如果你有很多东西要画,用户会以闪烁的形式注意到这一点。相反,你所有的绘图都是在屏幕外的图像(缓冲区)上进行的。然后,当您准备好时,交换屏幕外缓冲区,使其现在在屏幕上绘制。这种交换发生得非常快,因为它通常只是更新指针

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

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

我之所以说variant,是因为上面的代码没有交换缓冲区。相反,您正在将屏幕外的缓冲区
I
复制到屏幕上的缓冲区。它仍然可以消除闪烁,因为所有渲染工作都是在屏幕外完成的。复制图像仍然非常快


第二个
Graphics
对象就在那里,因为您应该在绘图时始终使用组件提供的对象。因此,上面的代码向图像对象请求其图形对象。但是,没有真正的理由将
g2
存储为成员变量,您只需在
update
中每次请求它双缓冲的概念是绘图速度慢,如果你有很多东西要画,用户会以闪烁的形式注意到这一点。相反,你把所有的绘图都放在屏幕外的图像(缓冲区)上。当你准备好了,你就交换屏幕外的缓冲区