canvas教程

[Java]双缓冲技术

字号+ 作者:H5之家 来源:H5之家 2017-09-15 13:08 我要评论( )

我们很多用Java中的g.drawImage()方法导入图像时,如果我们将当前窗口转变成非当前窗口状态,再从非当前窗口恢复到当前窗口状态,有时,某些绘制好的图像会消失

我们很多用Java中的g.drawImage()方法导入图像时,如果我们将当前窗口转变成非当前窗口状态,再从非当前窗口恢复到当前窗口状态,有时,某些绘制好的图像会消失,除非我们重新刷新窗口,显示才会恢复正常。此外,当我们移动窗口或者其他的窗口在上移动的时候,图像会有些闪烁。这是怎么一回事呢?这就要涉及到Canvas中的paint方法的绘图机制了。产生这种现象的主要原因是:

1、由于在显示所绘制的图像时,调用了repaint方法。repaint方法被调用时,需要清除整个背景,然后才调用paint方法显示画面。这样,在清除背景和绘制图像的短暂时间间隔内被用户看见的就是闪烁。

2、由于paint()方法需要进行复杂的计算,图像中包含着多个图形,不同图形的复杂程度及其所需要的绘制时间不同,因此,图像中的各个像素值不能同时产生,使得图形的生成频率低于显示器的刷新频率,从而造成闪烁。

下面两种方法可以明显地消除或减弱闪烁:

1、重载update方法

当AWT接收到Canvas重新绘制的请求时,调用Canvas的update方法。默认情况下,update方法清除Canvas的背景,然后调用paint方法。重载update方法,就可以将以前在paint方法中的绘图代码包含在update方法中,从而避免每次重新绘制时将整个区域清除。

2、双缓冲技术

双缓冲技术在很多动画中被采用。主要原理是创建一幅BufferedImage图像,将每一帧画入图像,然后调用drawImage方法,将整个BufferedImage图像一次画到屏幕上去。这种方法的优点在于大部分绘制是在BufferedImage进行的。将BufferedImage绘制的图像一次绘制到屏幕上。首先通过调用newBufferedImage方法生成合适的缓冲区,然后获得在缓冲区的绘图环境(即Graphics类对象)。

综上所述,我们导入图像的思路是:不直接在paint方法中调用各种绘制方法,而是采用重载update方法及双缓冲技术,生成一个图像的缓冲区,获得该缓冲区中的绘图环境后,将该绘图环境读入内存。paint方法不再负责图像的绘制工作,即paint方法不再装入任何的图像绘制代码。我们在paint方法中,直接调用update方法,在内存缓冲区的绘图环境下进行图像的绘制工作,当所有的图像绘制工作完成后,最后将缓冲区的内容一次性地写入Canvas并在窗口中直接显示出来。这种方法很巧妙地解决了图像丢失和闪烁的问题。

例子代码如下:

packageorg.lyndon.test;

importjava.awt.Canvas;

importjava.awt.Dimension;

importjava.awt.Graphics;

importjava.awt.Image;

importjava.awt.image.BufferedImage;

importjavax.swing.ImageIcon;

publicclassMyCanvasextendsCanvas{

privatestaticfinallongserialVersionUID=1L;

//窗体的宽与高

publicstaticfinalintWIDTH=480;

publicstaticfinalintHEIGHT=480;

privateImagescreen=createImage(WIDTH,HEIGHT,true);//双缓冲

privateGraphicsgraphics=screen.getGraphics();

privateImageresultImage;

/**

*生成一个BufferImage

*生成一个BufferImageBufferImage是Image的子类,左上角坐标都为(0,0)

*第三个参数是代码Image图形类型,分为14种,以位数又分为1,2或4位

*

*@paramwidth

*@paramheight

*@paramflag

*@return

*/

finalstaticpublicBufferedImagecreateImage(intwidth,intheight,

booleanflag){

if(flag){

returnnewBufferedImage(width,height,2);

}else{

returnnewBufferedImage(width,height,1);

}

}

publicMyCanvas(){

//设定初始构造时面板大小

setPreferredSize(newDimension(WIDTH,HEIGHT));

//初始导入一张图片

ImageIconicon=newImageIcon("image/floor.gif");

resultImage=icon.getImage();

}

//

@Override

publicvoidupdate(Graphicsg){

graphics.drawImage(resultImage,0,0,this);

g.drawImage(screen,0,0,null);//最后个参数一定要用null,这样可以防止drawImage调用update方法

g.dispose();

}

publicvoidpaint(Graphicsg){

update(g);//我们在paint方法中,直接调用update方法

}

}

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • java中除Canvas类可以画图外,还有其它类吗?

    java中除Canvas类可以画图外,还有其它类吗?

    2017-09-13 17:00

  • webpack前端技术小结

    webpack前端技术小结

    2017-09-12 18:16

  • HTML5的javascript touch事件

    HTML5的javascript touch事件

    2017-09-12 08:07

  • java绘图程序

    java绘图程序

    2017-09-11 16:02

网友点评