标签:
这里先给出一段代码,功能是用键盘控制屏幕上的一个小矩形移动:
import java.awt.Color; import java.awt.Frame; import java.awt.Graphics; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class MainWindow extends Frame implements KeyListener{ final int WINDOW_WIDTH=800; final int WINDOW_HEIGHT=700; final int WINDOW_X=100; final int WINDOW_Y=100; final String title="坦克大战"; final Color backgroundColor=Color.green; public int tank_x=100; public int tank_y=100; public MainWindow(){ this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } }); this.addKeyListener(this); this.setSize(WINDOW_WIDTH, WINDOW_HEIGHT); this.setLocation(WINDOW_X, WINDOW_Y); this.setTitle(title); this.setBackground(backgroundColor); } public void paint(Graphics g){ g.setColor(Color.red); g.fillRect(tank_x, tank_y, 30, 30); } public static void main(String[] args) { MainWindow mainWindow=new MainWindow(); mainWindow.setVisible(true); } public void keyPressed(KeyEvent arg0) { if(arg0.getKeyCode()==KeyEvent.VK_UP) tank_y-=1; if(arg0.getKeyCode()==KeyEvent.VK_DOWN) tank_y+=1; if(arg0.getKeyCode()==KeyEvent.VK_LEFT) tank_x-=1; if(arg0.getKeyCode()==KeyEvent.VK_RIGHT) tank_x+=1; repaint(); } public void keyReleased(KeyEvent arg0) { } public void keyTyped(KeyEvent arg0) { } }
<img src="http://img.blog.csdn.net/20160329003219365?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
<div style="font-family: 'Microsoft YaHei', 'Helvetica Neue', SimSun; line-height: 21px; color: rgb(73, 73, 73); font-size: 14px; background-color: rgb(197, 208, 129);"><span style="word-wrap: normal; word-break: normal; line-height: 25px; font-size: 13pt; font-family: Consolas;">这段代码成功实现了用键盘控制矩形移动的功能,但是有个严重的问题就是矩形在运动的过程中有严重的闪烁,这一点让人头疼,要解决问题,咱们得先找到问题,先来分析一下代码吧:</span></div><div style="font-family: 'Microsoft YaHei', 'Helvetica Neue', SimSun; line-height: 21px; color: rgb(73, 73, 73); font-size: 14px; background-color: rgb(197, 208, 129);"><span style="word-wrap: normal; word-break: normal; line-height: 25px; font-size: 13pt; font-family: Consolas;"><span style="word-wrap: normal; word-break: normal; font-size: 13pt;">MainWindow</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">的对象建立后,程序会首先调用重写后的</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt;">paint()</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">方法,在窗口上绘制一个矩形,当我们按下键盘上的键时,矩形的坐标值已经改变了,我们调用</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt;">repaint()</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">这个方法,这个方</span></span></div><div style="font-family: 'Microsoft YaHei', 'Helvetica Neue', SimSun; line-height: 21px; color: rgb(73, 73, 73); font-size: 14px; background-color: rgb(197, 208, 129);"><span style="word-wrap: normal; word-break: normal; line-height: 25px; font-size: 13pt; font-family: Consolas;"><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">法会重新调用</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt;">paint()</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">方法,然后在新的位置画一个矩形,这里有一个问题就是在新的位置画了矩形之后,原来的矩形还在,这样矩形的运动就会留下“轨迹”,为了解决这个问题,</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt;">repaint()</span></span></div><div style="font-family: 'Microsoft YaHei', 'Helvetica Neue', SimSun; line-height: 21px; color: rgb(73, 73, 73); font-size: 14px; background-color: rgb(197, 208, 129);"><span style="word-wrap: normal; word-break: normal; line-height: 25px; font-size: 13pt; font-family: Consolas;"><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">方法在调用</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt;">paint()</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">方法的时候会先调用一个</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt;">update()</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">方法来把原来的屏幕清掉,然后</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt;">update()</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">方法再调用</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt;">paint()</span><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">方法在新的位置画一个矩形,这样就把矩形的运动轨迹给清掉了,达到了运动的</span></span></div><div style="font-family: 'Microsoft YaHei', 'Helvetica Neue', SimSun; line-height: 21px; color: rgb(73, 73, 73); font-size: 14px; background-color: rgb(197, 208, 129);"><span style="word-wrap: normal; word-break: normal; line-height: 25px; font-size: 13pt; font-family: Consolas;"><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;">效果。函数调用示意图如下:</span></span></div><div style="font-family: 'Microsoft YaHei', 'Helvetica Neue', SimSun; line-height: 21px; color: rgb(73, 73, 73); font-size: 14px; background-color: rgb(197, 208, 129);"><span style="word-wrap: normal; word-break: normal; line-height: 25px; font-size: 13pt; font-family: Consolas;"><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;"><img src="http://img.blog.csdn.net/20160329003555132?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /> </span></span></div><div style="font-family: 'Microsoft YaHei', 'Helvetica Neue', SimSun; line-height: 21px; color: rgb(73, 73, 73); font-size: 14px; background-color: rgb(197, 208, 129);"><span style="word-wrap: normal; word-break: normal; line-height: 25px; font-size: 13pt; font-family: Consolas;"><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;"><span style="word-wrap: normal; word-break: normal; line-height: 25px; color: rgb(73, 73, 73); font-family: Consolas; font-size: 13pt; background-color: rgb(197, 208, 129);">问题就发生在</span><span style="word-wrap: normal; word-break: normal; line-height: 25px; color: rgb(73, 73, 73); font-family: Consolas; font-size: 13pt; background-color: rgb(197, 208, 129);">update()</span><span style="word-wrap: normal; word-break: normal; line-height: 25px; color: rgb(73, 73, 73); font-family: Consolas; font-size: 13pt; background-color: rgb(197, 208, 129);">这个函数中,我们来看一下这个函数的源码:</span> </span></span></div><div style="font-family: 'Microsoft YaHei', 'Helvetica Neue', SimSun; line-height: 21px; color: rgb(73, 73, 73); font-size: 14px; background-color: rgb(197, 208, 129);"><span style="word-wrap: normal; word-break: normal; line-height: 25px; font-size: 13pt; font-family: Consolas;"><span style="word-wrap: normal; word-break: normal; font-size: 13pt; font-family: 微软雅黑, sans-serif;"><span style="word-wrap: normal; word-break: normal; line-height: 25px; color: rgb(73, 73, 73); font-family: Consolas; font-size: 13pt; background-color: rgb(197, 208, 129);"></span></span></span><pre name="code" class="java">public void update(Graphics g) { if (isShowing()) { if (! (peer instanceof LightweightPeer)) { g.clearRect(0, 0, width, height); } paint(g); } }代码的意思是:(如果该组件是轻量组件的话)先用背景色覆盖整个组件,然后再调用paint(Graphics g)函数,重新
public void update(Graphics g){ paint(g); }在这个函数里我们只调用paint函数而不做其他处理,运行结果如下:
public void update(Graphics g){ if(i==null) i=this.createImage(WINDOW_WIDTH, WINDOW_HEIGHT); Graphics ig=i.getGraphics(); ig.setColor(backgroundColor); ig.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); paint(ig); g.drawImage(i, 0, 0, null); }首先是让这个窗口生成一张图片:
i=this.createImage(WINDOW_WIDTH, WINDOW_HEIGHT);然后给这张图片涂上背景色:
Graphics ig=i.getGraphics(); ig.setColor(backgroundColor); ig.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);在这里重新定义了一只画笔ig,是这张纸自带的画笔,然后调用paint函数在纸上画个矩形:
paint(ig);最后把这张图片给画出来:
g.drawImage(i, 0, 0, null);
运行程序发现运动的矩形不再闪烁了,这样我们就完成了简单的双缓冲技术。
除了这种方法外,还可以在paint函数里做文章,原理也是一样,代码如下:
public void paint(Graphics g){ if(i==null) i=this.createImage(WINDOW_WIDTH, WINDOW_HEIGHT); //生成一张纸 Graphics ig=i.getGraphics(); //定义一只新画笔 ig.setColor(backgroundColor); //给画笔选颜色 ig.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); //给这张纸涂上背景色 ig.setColor(Color.red); //设置画笔颜色 ig.fillRect(tank_x, tank_y, 30, 30); //在屏幕上画一个圆 g.drawImage(i, 0, 0, null); } //下面这个函数是实现双缓冲的 public void update(Graphics g){ paint(g); //调用paint函数在纸上画矩形 }
我们在update函数里只调用paint函数,而在paint函数里实现了双缓冲,两种方法原理一样,要灵活掌握,这里给出双缓冲的一般步骤:
(1)定义一个Graphics对象ig和一个Image对象i。按屏幕大小建立一个缓冲对象给i。然后取得i的Graphics赋给ig。此处可以把ig理解为逻辑上的缓冲屏幕,而把i理解为缓冲屏幕上的图象。
(2)在ig(逻辑上的屏幕)上用paint(Graphics g)函数绘制图象。
(3)将后台图象i绘制到前台。
以上就是一次双缓冲的过程。注意,将这个过程联系起来的是repaint()函数。paint(Graphics g)是一个系统调用语句,不能由程序员手工调用。只能通过repaint()函数调用。
标签:
原文地址:http://blog.csdn.net/u013189927/article/details/51002503