a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 124|回复: 0

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

[复制链接]
发表于 2012-8-4 12:44:44 | 显示全部楼层 |阅读模式
现在我们明白了,屏幕上之所以出现闪烁是因为在update()方法内先要哗哗的清空屏幕上原有的东西,然后又哗哗的往上画,所以在我们需要不断重绘的屏幕上出现闪烁是必然的了,哪怕CPU的速度快之又快。  i0 P4 W3 E* Y5 t- e
    通过上述的分析,在awt中我们解决闪烁问题的思路也因该随之产生,即重写update()函数的代码,改变它的工作原理。于是我们引进一段在坦克大战中已经重写了的update()方法。其中通过改变重绘函数paint(g)重绘的画布对象,由窗体的画布变为截取的图片上的画布gImage,这样的话就很大程度上改善这个问题了。具体如下) w% M& B' m+ E9 F6 g
    Java代码
- ]# f: Z8 g* \, c    // 重写update方法,先将窗体上的图形画在图片对象上,再一次性显示" c6 a: l+ r7 x3 W% W
    public void update(Graphics g) {+ [9 A+ ]" V0 z( V$ ^
    if (offScreenImage == null) {( J6 z7 B  Y* e# E; ^
    // 截取窗体所在位置的图片1 M0 m* X) R7 C0 `
    offScreenImage = this.createImage(WIDTH, HEIGHT);
: e9 v+ }& v! X# d    }) S; f( F' |  l% ^* K- w
    // 获得截取图片的画布
1 f6 [* a# g+ \# s) }3 a, t8 C    Graphics gImage = offScreenImage.getGraphics();, i* ?. k1 m& z; f. u" i4 l- A/ a+ t
    // 获取画布的底色并且使用这种颜色填充画布(默认的颜色为黑色): v3 i1 u& {! F$ w. V2 N
    Color c = Color.BLACK;
. S+ R  c6 T+ C! ~( @: e$ v    gImage.setColor(c);: ~# R# i: M' O/ P4 ~1 @
    gImage.fillRect(0, 0, WIDTH, HEIGHT); // 有清除上一步图像的功能,相当于gImage.clearRect(0, 0, WIDTH, HEIGHT)/ A+ k/ h' C+ R" u. u
    // 将截下的图片上的画布传给重绘函数,重绘函数只需要在截图的画布上绘制即可,不必在从底层绘制) z' R* F& `5 a/ |
    paint(gImage);
$ y2 c8 H* ^6 {/ V+ |4 Y    //将接下来的图片加载到窗体画布上去,才能考到每次画的效果) V! b% o1 U! f5 ~  v" @$ w
    g.drawImage(offScreenImage, 0, 0, null);
+ K  C$ C4 q8 n; m% i    }
* I, V$ d! C1 n/ q! _( u    其实一言以蔽之就是通过重写update()方法改变重绘函数paint(g)重绘的画布对象g。, r9 [: R- g4 Y0 D3 L- a" U
    以上的讨论我们都是在awt中进行,然后大家就想将继承Frame改为JFrame试试,结果一试就傻眼了,屏幕上居然又是哗哗的闪了,真是辛辛苦苦去改变,一下回到解放前,我们不是在update()中实现双缓冲机制了吗?请看下面的一个对比测试:
6 D; T) ?) b* Z. V  h1 m4 o    (1)在awt中测试update():
6 `0 H  c$ w! D/ |    Java代码& a* ]( ]  b; y1 @$ Z" l" i8 W( o+ e
    // 重写update方法,先将窗体上的图形画在图片对象上,再一次性显示
0 _( _! l& W2 H/ ~& ^6 a    public void update(Graphics g) {+ s1 J2 E8 M6 T9 b
    System.out.println("awt的update()在此...");$ U. z" b: Z( i
    if (offScreenImage == null) {
# u. y( F0 H8 r% w. k9 s! N. M' \    // 截取窗体所在位置的图片  A( `* ?  y2 s
    看看结果:
3 D# K+ r% ^" c! G1 g# \    要是没觉得意外的话就继续往下看
6 n* ^9 ~2 o- j- z+ E. j. W. \    在swing中测试update():
2 {" V4 _- x7 x' Z8 c, e2 i1 [/ U    Java代码' k' |2 B+ e; c5 A, U' x
    // 重写update方法,先将窗体上的图形画在图片对象上,再一次性显示* F1 L5 F" f) e9 G; r+ ]
    public void update(Graphics g) {
0 V/ c6 d% {5 `4 h* E    System.out.println("Swing的update()在此...");( V$ r8 K# G$ V, h0 a4 K! P: b
    if (offScreenImage == null) {
0 t1 ~6 |7 L$ r! v( v1 e, J    // 截取窗体所在位置的图片
( o" s; B8 D$ I+ d  B0 ~" ]    结果是:
2 O& V$ P& y: h, j( ]    是不是有点吃惊了,在我没有故意编出这个东西忽悠大伙的前提下我们可以得知,在swing中update()方法并没有像awt的update()那样随时被调用,所以就很好解释为什么该为继承JFrame之后屏幕重绘闪烁了。就是你认为自己改写了update()方法就会解决这个问题是一厢情愿的,系统并不买你的帐,调都没去调用呐!
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-6 19:45 , Processed in 0.208508 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

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