+ -
当前位置:首页 → 问答吧 → 关于双缓冲解决闪烁现象出现的问题,求助!!!

关于双缓冲解决闪烁现象出现的问题,求助!!!

时间:2011-12-02

来源:互联网

前言:刚接触双缓冲机制,有个问题我现在的能力无法解决,所以走上csdn求助,望各位大哥不吝赐教。
问题描述:我所认知的观点是1.repaint()方法能主动调用paint()方法从而使图像重画;2.repaint()方法调用的频率过快会使得paint()方法没来得及执行完毕而被下一个repaint()方法调用的paint()方法冲掉而产生闪烁现象,所以要引进双缓冲机制;3.双缓冲是指repaint()方法在调用paint()方法前先(或者同时)调用update()方法使图像先画在虚拟图像上在与电脑屏幕融合;
问题:当我用Eclipse重写update()方法(自动引入)的时候,出来的update()方法体中会自动执行“super.update();”语句,如下代码。问题就出现在这里,当我按照常规程序在虚拟图像offScreen上画完所需图形,用drawImage()方法把虚拟图像融合到电脑屏幕中后,闪烁现象依然,但是当我注掉“super.update();”这句代码后问题解决,我搞不清楚的是,这句代码为何要出现,我印象中只有子类实例化的时候才会先执行父类的构造方法,那么为什么子类重写父类方法的时候也要先让父类对象调用一下要重写的方法呢?就算是执行了“super.update();”,这句话又是怎样影响到双缓冲的进行的呢?

public   void   update(Graphics   g)   {
  super.update(g);//自动产生,注掉后,闪烁现象消失。
  if   (offScreen   ==   null){
  offScreen   =   this.createImage(800,600);
  }
  Graphics   goffScreen   =   offScreen.getGraphics();
  Color   c   =   goffScreen.getColor();
  goffScreen.setColor(Color.green);
  goffScreen.fillRect(0,0,800,600);
  goffScreen.setColor(c);
  paint(goffScreen);
  g.drawImage(offScreen,0,0,null);

}

作者: disalong   发布时间: 2011-12-02

建立一张空白的image对象,然后这个image获取graphics 然后把所有的东西都画到这个image上面,然后 窗体draw这个image。懂了吗

作者: luciferdevil   发布时间: 2011-12-02

不好意思没看清楚代码,我都没用过update ,直接用线程定时去draw的,这样可以自己控制绘图帧数

作者: luciferdevil   发布时间: 2011-12-02

先感谢楼上的回答,关于draw以及如何draw的做法可能会因需求而不同,我只是认为“super.update()”必然影响了虚拟图画draw到电脑屏幕的过程,才会使得闪烁现象依然,不解的是内部是如何影响的

作者: disalong   发布时间: 2011-12-02

顶上去

作者: disalong   发布时间: 2011-12-02


仔细看文档
只是调用 paint(g)。重写此方法,以防止不必要的调用清除背景

注意看!! 以防止 不必要的清除屏幕! 而你 又自己 去 调用 super.update 去清除屏幕 呼``` 当然就会 有闪屏的现象 是你 自己清除 屏幕 然后 又画你的内容

作者: privateTia   发布时间: 2011-12-02


仔细看文档
只是调用 paint(g)。重写此方法,以防止不必要的调用清除背景

注意看!! 以防止 不必要的清除屏幕! 而你 又自己 去 调用 super.update 去清除屏幕 呼``` 当然就会 有闪屏的现象 是你 自己清除 屏幕 然后 又画你的内容

作者: privateTia   发布时间: 2011-12-02


仔细看文档
只是调用 paint(g)。重写此方法,以防止不必要的调用清除背景

注意看!! 以防止 不必要的清除屏幕! 而你 又自己 去 调用 super.update 去清除屏幕 呼``` 当然就会 有闪屏的现象 是你 自己清除 屏幕 然后 又画你的内容

作者: privateTia   发布时间: 2011-12-02

你对双缓冲的理解不太对。你的代码不能实现双缓冲。

另外,如果需要重载update,那么同时要重载paint。

JDK API 上面有详细的说明。

作者: lfp001   发布时间: 2011-12-02

Sorry Sorry 
我发那么多边 不是我的本意`!! 靠靠靠 是浏览器 自己的毛病 我郁闷 !!!!

作者: privateTia   发布时间: 2011-12-02

引用 5 楼 privatetia 的回复:
仔细看文档
只是调用 paint(g)。重写此方法,以防止不必要的调用清除背景

注意看!! 以防止 不必要的清除屏幕! 而你 又自己 去 调用 super.update 去清除屏幕 呼``` 当然就会 有闪屏的现象 是你 自己清除 屏幕 然后 又画你的内容


你好,源码是这样子的:启动一个子线程-》在run()方法里不断repaint()-》重写panint()与update()-》因为我要做一个图片的动态移动,所以必须每次调用update()方法都要重刷背景再画图片,paint()的调用只是想用已重写的paint()方法的画图模式在虚拟画面上作图以减少不必要的操作,这些都不影响虚拟图片draw的过程,我只是想知道update()中的”super.update(g);"这句话干嘛来着···
  private class PaintThread implements Runnable {
public void run() {
while(true) {
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


public void paint(Graphics g) {
Color c = g.getColor();
g.setColor(Color.RED);
g.fillOval(x, y, 30, 30);
g.setColor(c);

y += 5;
}

public void update(Graphics g) {
 super.update(g);//自动产生,注掉后,闪烁现象消失。
if(offScreenImage == null) {
offScreenImage = this.createImage(800, 600);
}
Graphics gOffScreen = offScreenImage.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.GREEN);
gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage, 0, 0, null);
}

作者: disalong   发布时间: 2011-12-03

楼主看的书应该是比较老的,如果使用Swing,绘制图形还是在paintComponent里做好一些

作者: Inhibitory   发布时间: 2011-12-03

顶一下

作者: w624431   发布时间: 2011-12-03

引用 11 楼 inhibitory 的回复:
楼主看的书应该是比较老的,如果使用Swing,绘制图形还是在paintComponent里做好一些


恩,是老的,在学基础,谢谢这位大哥

作者: disalong   发布时间: 2011-12-03



我只是想知道update()中的”super.update(g);"这句话干嘛来着···

 super.update 就是 调用 父类的update 父类中的 update 就是调用paint (原因 为啥要 委托给 update ? 就是 为了线程安全 与 优化绘制)

还有 就是 J中也要 根据情况 进行 paint复写的 毕竟有些时候 我们不想让 paint 过多干预我们的结果 这个 跟 新老书没什么关系 应该算常识才对 (写书作者 水平足够高的话 反正 我学 swing 和 awt 也不算新手了 但是 具体实现细节还是不知道的 囧 因为看不懂 源码) 虽然 有些时候 复写那个 结果都一样 但是 还是要知道差别的

作者: privateTia   发布时间: 2011-12-03