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

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

1.  先还是看看 Java API 中的介绍吧:update public void update(Graphics g)     更新组件。
    如果此组件不是轻量级组件,则为了响应对 repaint 的调用,AWT 调用 update 方法。可以假定未清除背景。
    Component 的 update 方法调用此组件的 paint 方法来重绘此组件。为响应对 repaint 的调用而需要其他工作的子类通常重写此方法。重写此方法的 Component 子类应该调用 super.update(g),或者直接从其 update 方法中调用 paint(g)。
    图形上下文的原点,即它的(0,0)坐标点是此组件的左上角。图形上下文的剪贴区域是此组件的边界矩形。
repaint  public void repaint()   重绘此组件。    

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

2. 引文地址:http://jimobit.blog.163.com/blog/static/2832577820100121066802/   

应用程序不应直接调用 paint,而是应该使用 repaint 方法来安排重绘组件

repaint -> update -> paint

重量级组件:    重写update方法 

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

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

 3.引文地址:百度空间http://hi.baidu.com/yuji0228/blog/item/116917394bea9dc8d462256a.html

repaint,update和paint这三个方法在Component中定义,由于awt,swing组件都直接或间接继承自Component,所以几乎所有的awt,swing组件都有这三个方法.这三个方法主要是用于组件的界面绘制.这三个方法执行顺序repaint() - update() - paint()一般在程序中我们都会重装paint()方法以执行重绘画面的动作,但实际上除了paint()以后,update()也执行了一部分的工作,这部分工作包括用默认的背景颜色填充,设置前景色等,由于这部分一般都无须用户参考,所以一般都update()自动完成,然后update()再调用paint()执行用户自定义的绘制操作.
一般情况不用重写update()方法。但是如果你填充背景的颜色跟paint()中的颜色不一样的时候就会有闪烁感。可以重写update方法,事实上,在用双缓冲画图时,一般都会选择重装update()而不是paint()方法,由于在执行paint()方法之前,update()还执行填充背景的动作,所以当重绘的速度很大时,填充背景的动作将很明显,也即闪烁很大,也将,如果在paint()中用双缓冲的话实际上起不了效果.而如果用update()的话就可以双缓冲达到预期的效果.
    当在程序中需要重绘操作时,我们一般会用repaint()而不是直接调用update()或者paint(),repaint()将调用update().而在各种awt,swing组件需要自动重新绘制时,程序也一般也会自动调用repaint()方法.

 下列就是本人今天做了欢迎介面时遇到的种种困难和错误,希望放在这里能让大家引以为鉴,不要再犯这样的错误!
 1、不理解paint()方法、repaint()方法、update()方法的区别;
 解决思路:paint()方法是由系统自动随机调用,而update()方法是我们自己人为调用,paint()方法必须要人为指定是什么时候让系统开始调用,但是首先在最开始的时候自己调用一次,所以不安全,我们一般使用update()方法,此方法必须用repaint()方法调用。我们调用paint()方法其实也是由repaint()方法调用update()方法(注:paint()方法在加图之前必须判断内存里面是否有图片);
 2、程序执行顺序问题:this.memoryImage()!=null;
 解决思路:虚拟机是先加载属性文件;
 3、路径错误;
 解决思路:src是源文件,不要和它混在一起,我们要用到其它如图片和音乐的文件要放在一个文件夹下面,且此文件夹是和src同一级别;
 4、找不到图片;
 解决思路:图片都必须是在媒体跟踪器跟踪完之后才能加载,才能找到其的宽和高,不能在媒体跟踪器加载完之前调用图片的宽和高;
 5、图片覆盖;
 解决思路:图片在画进屏幕的时候要有一定的顺序问题,背景放在最下面,一层一层往上放,要不然会发生覆盖问题;
 6、图片不能显示;
 解决思路:我们的图片画在屏幕上但前题是我们要有一个窗体才能画,所以在将内存的图画进屏幕的时候必须将窗体可见性设出:setVisible(true);
 7、未找到图片的问题判断:
 解决思路:如果没有找到图片,那么那个图片点whith及点height打印出来都是-1;

    关于上面提到的双缓冲问题,一个最好的解决办法就是重写 update 方法。 

总结:三个方法的调用顺序是没有错的,然后,对于轻量级组件,一般是重写 paint 方法以快速的绘制组件,但是对于重量及组件,由于重新绘制时间长,容易产生闪烁的现象,所以一般是采用重写 update 方法,利用双缓冲图片来解决闪烁的问题。


嘿嘿,各位写代码也有点累了吧,特别是深夜的时候是不是觉得应该有点吃的就更好了?可以到本人开的小店“小灰灰休闲美食”店买点休闲食品哦,既满足食欲又可以放松哈子,当然平时也要吃是吧,也可以买来送朋友哦!

你可能感兴趣的:(java,工作,虚拟机,swing,图形)