其实消除缓冲有很多方法,不一定要使用缓冲,先要了解闪烁产生的原理,(对于AWT)闪烁的主要原因是由于APPLET中的update()方法,一旦你在applet中显示图象,调用构件中的repaint()方法会接着默认调用构件的update()方法,而在默认方式下,update()方法是先清除构件中所有的背景,并调用构件的paint()方法,所以每次得到一行新的扫描线,repaint()会被调用,导致update()调用,清除背景并调用paint()所以这些清除和重画动作导致了闪烁,知道了这点,消除闪烁很简单,直接覆盖update()方法,直接调用paint90方法,
  public void update(Graphics g){
paint(g);
}
这样该update9)方法不会引起闪烁 :--)

解决方案 »

  1.   

    lvz(红心)的方法很好。
    http://www.csdn.net/expert/topicview1.asp?id=56117
    有介绍双缓冲技术的。
      

  2.   

    applet用渐长的方式显示图象,所以显示图象的速度非常慢。从磁盘文件装入图象时,许多applet为了改善显示效果而采用了双缓冲的方法:首先把图象装入内存,然后显示在屏幕。使用这种双缓冲技术的时候,applet必须实现imageUpdate函数,applet通过它来监视drawImage线程把图象装入内存的情况。整幅图象装入内存后,applet显示图象的时候就不会有班驳现象。
    如下的程序BufferDemo1.java和BufferDemo2.java分别演示了使用双缓冲技术显示图象的效果:
     import java.awt.*;
     import java.applet.*;
     
     public class BufferDemo1 extends Applet {
        //声明实例变量
        Image img1;
        Image img2;
        //调用getImage()方法给img1和img2赋值
        public void init() {
            img1 = getImage(getCodeBase(), "e.gif");
            img2 = getImage(getCodeBase(), "f.gif");
        }
        //调用drawImage()方法将img1和img2在applet窗格中显示
        public void paint(Graphics g) {
            g.drawImage(img1, 0, 0, this);
            g.drawImage(img2, 100, 100, this);
        }
     }
    编译之后运行BufferDemo1.java的时候会看到图象绘制的时候有班驳的现象,因为程序不是在drawImage函数返回之前把图象完整地装入并显示的。与此相反,drawImage函数创建了一个线程,该线程与applet的原有执行线程并发执行,它一边装入一边显示,从而产生了这种现象。
    如下的程序BufferDemo2.java演示了如何使用这种双缓冲技术来克服上述的问题:
     import java.awt.*;
     import java.applet.*;
     
     public class BufferDemo2 extends Applet {
        //声明实例变量
        Image img1;
        Image img2;
        boolean imageLoaded = false;
        boolean oneLoaded = false;
        boolean twoLoaded = false;
        
        public void init() {
            img1 = getImage(getCodeBase(), "e.gif");
            img2 = getImage(getCodeBase(), "f.gif");
            //创建了一个Image对象tmpImage,调用createImage函数将结果赋给它
            Image tmpImage = createImage(size().width, size().height);
            //创建了一个Graphics对象tmpGC,并把隐藏的图象设置赋值给该对象
            Graphics tmpGC = tmpImage.getGraphics();
            //调用drawImage函数显示图象
            tmpGC.drawImage(img1, 0, 0, this);
            tmpGC.drawImage(img2, 100, 100, this);
        }
        //paint函数的处理过程由布尔变量imageLoaded控制,当变量值为true时,paint函数调用
      //drawImage函数显示图象. 
        public void paint(Graphics g) {
            if(imageLoaded) {
        //此时调用drawImage函数时最后一个参数为null表示drawImage函数不调用//imageUpdate函数,因为图象已经驻留在内存中.
                g.drawImage(img1, 0, 0, null);
                g.drawImage(img2, 100, 100, null);
            }
            else {
                showStatus("Loading...");
            }
        }
        public boolean imageUpdate(Image img, int flag, int x, int y, int width, int height) {
            if(flag == ALLBITS) {
                oneLoaded = true;
            }
            else {
                twoLoaded = true;
            }
            imageLoaded = (oneLoaded&&twoLoaded);
            if(imageLoaded) {
                repaint();
                return false;
            }
            else {
                return true;
            }
        }
     }
    imageUpdate函数帮助应用程序确定图象是否已经全部装载入内存,applet每次调用drawImage函数的时候,该函数就会创建一个线程去调用imageUpdate函数,线程调用imageUpdate函数直到函数的返回值为false,也就是图象被完全装入内存。参数flag为AllBits就代表图象已经全部被装入内存,然后函数把imageLoaded赋值为true,并调用repaint函数显示applet窗口,最后函数返回false,停止执行drawImage线程。
      

  3.   

    在jdk1.3的文档中:
    If the system property awt.image.incrementalDraw
    is missing or has the value true, the image is
    incrementally drawn, If the system property has any other value,
    then the image is not drawn until it has been completely loaded.
    如果预先设置系统属性awt.image.incrementalDraw=false那么系统默认完全载入才会显示。