a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 133|回复: 0

[专业语言] JAVA认证:双缓冲原理在实现如何消除闪烁(2)

[复制链接]
发表于 2012-8-4 12:44:44 | 显示全部楼层 |阅读模式
现在我们明白了,屏幕上之所以出现闪烁是因为在update()方法内先要哗哗的清空屏幕上原有的东西,然后又哗哗的往上画,所以在我们需要不断重绘的屏幕上出现闪烁是必然的了,哪怕CPU的速度快之又快。- i. C  l9 ^7 {3 l8 \
    通过上述的分析,在awt中我们解决闪烁问题的思路也因该随之产生,即重写update()函数的代码,改变它的工作原理。于是我们引进一段在坦克大战中已经重写了的update()方法。其中通过改变重绘函数paint(g)重绘的画布对象,由窗体的画布变为截取的图片上的画布gImage,这样的话就很大程度上改善这个问题了。具体如下
; }8 Z8 _2 U. G$ g/ `    Java代码
$ Z& \  D  K/ h1 t0 R7 N    // 重写update方法,先将窗体上的图形画在图片对象上,再一次性显示4 ^6 l. K3 J6 d
    public void update(Graphics g) {' y0 z9 }) M+ p6 `7 s6 ?
    if (offScreenImage == null) {
+ e9 t* @0 V5 b    // 截取窗体所在位置的图片* s5 h5 e" M% s8 E5 f
    offScreenImage = this.createImage(WIDTH, HEIGHT);
! f8 B: J8 v+ b7 B8 ~    }
8 ]: Q: |5 Y6 J4 I6 B6 O. B( P    // 获得截取图片的画布2 w& b# c: j  |3 e9 M7 D& x. l
    Graphics gImage = offScreenImage.getGraphics();
, Y. Z- {: H, K0 U% n$ _# [    // 获取画布的底色并且使用这种颜色填充画布(默认的颜色为黑色)+ z! z. [- a  B& s& p6 a& }* r
    Color c = Color.BLACK;
; K4 u% H1 r0 U* Q* `* |    gImage.setColor(c);9 Q+ V( x" ^) l3 p" a" T1 @
    gImage.fillRect(0, 0, WIDTH, HEIGHT); // 有清除上一步图像的功能,相当于gImage.clearRect(0, 0, WIDTH, HEIGHT)
1 |0 H; {' }6 r4 }    // 将截下的图片上的画布传给重绘函数,重绘函数只需要在截图的画布上绘制即可,不必在从底层绘制
, i0 r8 E2 \, D- K    paint(gImage);
. I2 u3 _% D0 k8 j- o, V    //将接下来的图片加载到窗体画布上去,才能考到每次画的效果; P8 n; f3 |5 K8 \* l9 _: ]! i
    g.drawImage(offScreenImage, 0, 0, null);4 Y* \) X, }! X
    }
" o( [% \1 m) S$ o    其实一言以蔽之就是通过重写update()方法改变重绘函数paint(g)重绘的画布对象g。" }/ M; H" q5 |: l3 m4 j* c$ n' `/ F
    以上的讨论我们都是在awt中进行,然后大家就想将继承Frame改为JFrame试试,结果一试就傻眼了,屏幕上居然又是哗哗的闪了,真是辛辛苦苦去改变,一下回到解放前,我们不是在update()中实现双缓冲机制了吗?请看下面的一个对比测试:
. Y: {0 @: \% W    (1)在awt中测试update():* Q- O: x8 c  P! g* n
    Java代码
; A' Q. s" `6 R: f& i    // 重写update方法,先将窗体上的图形画在图片对象上,再一次性显示
6 `; D, G. v  L% f- s/ m' B    public void update(Graphics g) {* r* d9 ^( L1 D0 {$ T
    System.out.println("awt的update()在此...");
$ J" o" k- u1 l: N) e0 {    if (offScreenImage == null) {9 {% P& y; H9 D; f. H7 J
    // 截取窗体所在位置的图片0 ^, n) D* H$ Y$ t) k/ I* e  Z
    看看结果:0 y5 a7 A- p* i( o6 ^2 \
    要是没觉得意外的话就继续往下看6 e1 M* K4 o1 j7 q) q0 b$ |3 E. `
    在swing中测试update():
4 y$ d0 j  s: a0 h4 H( _    Java代码
, V$ Q  {& M. F9 C    // 重写update方法,先将窗体上的图形画在图片对象上,再一次性显示
: R. n- t, K: K) H0 [9 r    public void update(Graphics g) {4 P( v( e# w7 f9 V0 q# o
    System.out.println("Swing的update()在此...");
9 v. l0 r8 r5 }! i9 \. ~    if (offScreenImage == null) {8 x1 M/ {0 @& W: s8 e* U/ z
    // 截取窗体所在位置的图片0 y+ k9 N  U; E) ~9 d* D
    结果是:( z; D. L6 P+ _& x8 r( s6 }8 Y- O9 ~
    是不是有点吃惊了,在我没有故意编出这个东西忽悠大伙的前提下我们可以得知,在swing中update()方法并没有像awt的update()那样随时被调用,所以就很好解释为什么该为继承JFrame之后屏幕重绘闪烁了。就是你认为自己改写了update()方法就会解决这个问题是一厢情愿的,系统并不买你的帐,调都没去调用呐!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-6-26 11:27 , Processed in 0.310228 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表