关于Java中的paint,repaint,update三个方法的关系

这些天一直在用repaint()和paint(),到网上一查,还揪出了update(), 其中查到一篇介绍Java中的paint,repaint,update三个方法的关系的文章:<wbr></wbr>

1.先还是看看JavaAPI中的介绍吧:<wbr>update publicvoid<strong><wbr>update</wbr></strong><wbr>(Graphicsg)<span style="font-family:; line-height:1.3em">更新组件。</span><wbr><br><span style="font-family:; line-height:1.3em"></span><wbr><span style="font-family:; line-height:1.3em">如果此组件不是轻量级组件,则为了响应对repaint的调用,AWT调用update方法。可以假定未清除背景。</span><wbr><br> Component的update方法调用此组件的paint方法来重绘此组件。<span style="color:#ff0000; line-height:1.3em">为响应对repaint的调用而需要其他工作的子类通常重写此方法。重写此方法的Component子类应该调用super.update(g),或者直接从其update方法中调用paint(g)。</span><wbr><br> 图形上下文的原点,即它的(0,0)坐标点是此组件的左上角。图形上下文的剪贴区域是此组件的边界矩形。<br><u><wbr></wbr></u><wbr><span style="line-height:1.3em">repaint </span><span style="font-family:; line-height:1.3em">publicvoid<strong><wbr>repaint</wbr></strong><wbr>()重绘此组件。</wbr></span><wbr><span style="font-family:; line-height:1.3em"></span><wbr><span style="line-height:1.3em"></span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

如果此组件是轻量级组件,则此方法会尽快调用此组件的paint方法。否则此方法会尽快调用此组件的update方法。<wbr></wbr><wbr><span style="line-height:1.3em">paint public void paint(Graphics g) 绘制此组件。</span></wbr><wbr><u><span style="font-size:18px"></span></u><wbr><u><wbr></wbr></u><wbr><span style="font-size:18px"><span style="line-height:1.3em">出于性能的考虑,首次显示宽度或高度为0的Component时认为它不需要进行绘制,并且也不需要修复。</span><wbr><br><u><wbr></wbr></u><wbr><span style="line-height:1.3em">应该绘制组件的内容时调用此方法;例如首次显示组件或者组件已损坏并需要修复时。Graphics参数中的剪贴区矩形设置为需要绘制的区域。重写此方法的Component子类不需要调用super.paint(g)。</span></wbr></wbr></span></wbr></wbr></wbr>

<wbr><span style="line-height:1.3em"><span style="font-size:18px">2.引文地址:</span><a href="http://jimobit.blog.163.com/blog/static/2832577820100121066802/" target="_blank"><span style="font-size:18px">http://jimobit.blog.163.com/blog/static/2832577820100121066802/</span></a><wbr><span style="font-size:18px"></span></wbr></span></wbr>

<wbr><span style="line-height:1.3em"><span style="font-size:18px; color:#6e6e6e; line-height:1.3em">应用程序不应直接调用paint,而是应该使用repaint方法来安排重绘组件</span></span></wbr>

<wbr><strong><wbr><span style="font-size:18px; color:#6e6e6e; line-height:1.3em">repaint-&gt;update-&gt;paint</span></wbr></strong></wbr>

<wbr><strong><wbr><strong><wbr><span style="font-size:18px"><span style="color:#6e6e6e; line-height:1.3em">重量级组件:</span><wbr><strong><wbr><span style="color:#6e6e6e; line-height:1.3em"></span></wbr></strong></wbr></span></wbr></strong></wbr></strong></wbr>重写update方法

<wbr><strong><wbr><wbr><strong><wbr><span style="font-size:18px"><span style="color:#6e6e6e; line-height:1.3em">轻量级组件:</span><wbr><strong><wbr><span style="color:#6e6e6e; line-height:1.3em">尽快调用paint方法,此方法将绘制工作委托给三个受保护的方法:paintComponent、paintBorder和paintChildren。按列出的顺序调用这些方法,以确保子组件出现在组件本身的顶部。</span><wbr><strong><wbr><span style="color:#6e6e6e; line-height:1.3em">重写paintComponet方法</span><wbr><strong><wbr><strong><wbr><span style="color:#6e6e6e; line-height:1.3em">paint(g),一个回调方法,绝大多数时候组件的绘图逻辑都存储于这个方法中。awt系统会在适当的时候调用这个方法对组件进行绘图。容器在绘制的时候,容器的paint(g)方法默认会显示通知在容器中存在的所有visible为true的子组件进行绘制.</span><wbr><strong><wbr><strong><wbr><span style="color:#ff0000; line-height:1.3em">awt调用这个方法有2种形式。程序驱动方式和系统驱动方式。</span><wbr><strong><wbr><span style="color:#7030a0; line-height:1.3em">在</span><wbr><span style="color:#ff0000; line-height:1.3em">系统驱动</span><wbr><span style="color:#7030a0; line-height:1.3em">的情况下(比如界面第一次显示组件),系统会判断组件的显示区域,然后向事件分发线程发出调用paint(g)的命令.</span><wbr><strong><wbr><span style="color:#ff0000; line-height:1.3em">程序驱动</span><wbr><span style="color:#7030a0; line-height:1.3em">则由外部的程序调用repaint()方法提出一个异步请求.repaint方法会调用update(g)方法,update方法在默认情况下简单调用paint(g)方法.从而绘制组件.</span><wbr><strong><wbr><strong><wbr><span style="color:#6e6e6e; line-height:1.3em">一般不提倡将组件的具体绘制逻辑放到paint(g)之外,也不提倡程序直接调用paint(g)方法.需要注意的是,由于程序驱动方式是由程序来负责组件的绘制,所以repaint方法拥有几个重载方法.传入绘制区域,由程序决定组件的绘制区域.</span><wbr><strong><wbr><strong><wbr><span style="color:#6e6e6e; line-height:1.3em">update(g)方法.</span><wbr><span style="color:#ff0000; line-height:1.3em">在awt的重量级组件上,update是一个很重要的方法.在外部程序调用repaint的时候,都会调用到update.程序员通过继承重量级组件,覆盖这个update方法.可以实现自己的绘图逻辑,典型的用法是重新绘制组件需要改变的的一部份而不是全部(增量绘图).这样对于复杂的</span><wbr><strong><wbr><strong><wbr><span style="color:#0070c0; line-height:1.3em">组件绘制可以提高效率,不然在默认情况下,重量级组件的update将擦除组件的整个区域,并重新调用paint()方法从头绘制.不过轻量级组件不能采用这个方法.这是由于轻量级组件的本质造成的:</span></wbr></strong></wbr></strong></wbr></wbr></wbr></strong></wbr></strong></wbr></wbr></strong></wbr></strong></wbr></wbr></wbr></strong></wbr></wbr></wbr></wbr></strong></wbr></wbr></strong></wbr></strong></wbr></wbr></strong></wbr></strong></wbr></wbr></strong></wbr></wbr></strong></wbr></span></wbr></strong></wbr></wbr></strong></wbr>

<wbr><strong><wbr><strong><wbr><span style="color:#ff0000; line-height:1.3em">重量级组件和轻量级组件的区别</span><wbr><span style="color:#6e6e6e; line-height:1.3em">,在于前者拥有一个本地同位体,绘制和现实逻辑都是依靠本地系统来完成.而轻量级组件不依赖于任何本地系统.只需要一个重量级容器组件作为载体.在重量级组件的基础上,完全采用java的绘制代码(个人理解为graphics)来生成.所以轻量级组件在不显示的时候是透明的.甚至可以认为本组件不存在.由于轻量级组件没有采用任何本地系统代码来进行绘制,所以在需要绘制的情况下需要awt显式的通知,当这个通知来自于轻量级组件(就是指组件尺寸改变)而非本地系统时(指组件第一次进行绘制),这个通知采用调用repaint方法的形式进行.换句话说,</span><wbr><span style="color:#ff0000; line-height:1.3em">对于轻量级组件,即使是系统级驱动绘图,也可能会调用repaint方法.而repaint方法将会调用update方法,update方法默认调用paint方法.所以轻量级组件在系统驱动和程序驱动方式上的绘图并没有什么区别.</span><wbr><strong><wbr><strong><wbr><span style="color:#6e6e6e; line-height:1.3em">即使如此,也有办法对复杂的轻量级组件进行有效的增量绘图.复杂的轻量级组件都可以做成容器.可以根据一些内部信息,只绘制轻量级组件中某几个组件.典型做法是覆盖paint方法.</span></wbr></strong></wbr></strong></wbr></wbr></wbr></wbr></strong></wbr></strong></wbr>

<wbr></wbr><wbr><span style="line-height:1.3em"><span style="color:#6e6e6e; line-height:1.3em">3.引文地址:百度空间</span><wbr></wbr></span><wbr></wbr></wbr>http://hi.baidu.com/yuji0228/blog/item/116917394bea9dc8d462256a.html<wbr><br><br><span style="line-height:1.3em"><span style="font-size:18px"><span style="color:#7030a0; line-height:1.3em">repaint,update和paint<strong><wbr>这三个方法在Component中定义,由于awt,swing组件都直接或间接继承自Component,所以几乎所有的awt,swing组件都有这三个方法.这三个方法主要是用于组件的界面绘制.<strong><wbr>这三个方法执行顺序repaint()-update()-paint()<strong><wbr>一般在程序中我们都会重装paint()方法以执行重绘画面的动作,但实际上除了paint()以后,update()也执行了一部分的工作,这部分工作包括用默认的背景颜色填充,设置前景色等,由于这部分一般都无须用户参考,所以一般都update()自动完成,然后update()再调用paint()执行用户自定义的绘制操作.</wbr></strong></wbr></strong></wbr></strong></span><wbr><br><span style="color:#ff0000; line-height:1.3em">一般情况不用重写update()方法。但是</span><wbr><span style="color:#00b050; line-height:1.3em">如果你填充背景的颜色跟paint()中的颜色不一样的时候就会有闪烁感</span><wbr><span style="color:#ff0000; line-height:1.3em">。可以重写update方法,事实上,在用</span><wbr><span style="color:#0070c0; line-height:1.3em">双缓冲画图</span><wbr><span style="color:#ff0000; line-height:1.3em">时,一般都会选择重装update()而不是paint()方法,由于在执行paint()方法之前,update()还执行填充背景的动作,所以当重绘的速度很大时,填充背景的动作将很明显,也即闪烁很大,也将,如果在paint()中用双缓冲的话实际上起不了效果.而如果用update()的话就可以双缓冲达到预期的效果.</span><wbr></wbr></wbr></wbr></wbr></wbr></wbr></span><strong><wbr><span style="font-size:18px; color:#7030a0; line-height:1.3em"></span><wbr><strong><wbr><span style="font-size:18px"><span style="color:#7030a0; line-height:1.3em">当在程序中需要重绘操作时,我们一般会用repaint()而不是直接调用update()或者paint(),repaint()将调用update().而在各种awt,swing组件需要自动重新绘制时,程序也一般也会自动调用repaint()方法.</span><wbr><br><br><span style="color:#7030a0; line-height:1.3em">下列就是本人今天做了欢迎介面时遇到的种种困难和错误,希望放在这里能让大家引以为鉴,不要再犯这样的错误!</span><wbr><br><span style="color:#7030a0; line-height:1.3em">1、不理解paint()方法、repaint()方法、update()方法的区别;</span><wbr><br><span style="color:#7030a0; line-height:1.3em">解决思路:</span><wbr><span style="color:#ff0000; line-height:1.3em">paint()方法是由系统自动随机调用,而update()方法是我们自己人为调用</span><wbr><span style="color:#7030a0; line-height:1.3em">,paint()方法必须要人为指定是什么时候让系统开始调用,但是首先在最开始的时候自己调用一次,所以不安全,我们一般使用update()方法,此方法必须用repaint()方法调用。我们调用paint()方法其实也是由repaint()方法调用update()方法(注:paint()方法在加图之前必须判断内存里面是否有图片);</span><wbr><br><span style="color:#7030a0; line-height:1.3em">2、程序执行顺序问题:this.memoryImage()!=null;</span><wbr><br><span style="color:#7030a0; line-height:1.3em">解决思路:</span><wbr><span style="color:#ff0000; line-height:1.3em">虚拟机是先加载属性文件;</span><wbr><br><span style="color:#7030a0; line-height:1.3em">3、路径错误;</span><wbr><br><span style="color:#7030a0; line-height:1.3em">解决思路:src是源文件,不要和它混在一起,我们要用到其它如图片和音乐的文件要放在一个文件夹下面,且此文件夹是和src同一级别;</span><wbr><br><span style="color:#7030a0; line-height:1.3em"><strong><wbr>4</wbr></strong><wbr>、找不到图片;</wbr></span><wbr><br><span style="color:#7030a0; line-height:1.3em">解决思路:</span><wbr><span style="color:#ff0000; line-height:1.3em">图片都必须是在媒体跟踪器跟踪完之后才能加载,才能找到其的宽和高,不能在媒体跟踪器加载完之前调用图片的宽和高;</span><wbr><br><span style="color:#7030a0; line-height:1.3em">5、图片覆盖;</span><wbr><br><span style="color:#7030a0; line-height:1.3em">解决思路:图片在画进屏幕的时候要有一定的顺序问题,背景放在最下面,一层一层往上放,要不然会发生覆盖问题;</span><wbr><br><span style="color:#7030a0; line-height:1.3em">6、图片不能显示;</span><wbr><br><span style="color:#7030a0; line-height:1.3em">解决思路:我们的图片画在屏幕上但前题是我们要有一个窗体才能画,所以在将内存的图画进屏幕的时候必须将窗体可见性设出:setVisible(true);</span><wbr><br><span style="color:#7030a0; line-height:1.3em">7、未找到图片的问题判断:</span><wbr><br><span style="color:#7030a0; line-height:1.3em">解决思路:</span><wbr><span style="color:#ff0000; line-height:1.3em">如果没有找到图片,那么那个图片点whith及点height打印出来都是-1</span><wbr><span style="color:#7030a0; line-height:1.3em">;</span><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></span></wbr></strong></wbr></wbr></strong></span><wbr><span style="font-family:; line-height:1.3em"><span style="color:#7030a0; line-height:1.3em"><br></span></span><span style="font-family:; line-height:1.3em"><span style="font-size:18px; color:#7030a0; line-height:1.3em"> 关于上面提到的双缓冲问题,一个最好的解决办法就是重写update方法。</span></span></wbr></wbr>

<wbr><span style="line-height:1.3em"><span style="font-size:18px; color:#ff0000; line-height:1.3em">总结:三个方法的调用顺序是没有错的,然后,对于轻量级组件,一般是重写paint方法以快速的绘制组件,但是对于重量及组件,由于重新绘制时间长,容易产生闪烁的现象,所以一般是采用重写update方法,利用双缓冲图片来解决闪烁的问题。</span><wbr></wbr></span><wbr><span style="color:#070c0; line-height:1.3em"><br></span></wbr></wbr>

你可能感兴趣的:(update)