日期:2014-05-20  浏览次数:20591 次

repaint() paint() update()重量级 轻量级
本人查找了许多网页 都说系统会自动调用repaint() 然后 如果是重量级组件 则repaint()调用 update() 而update()再调用paint()
而且API文档貌似也是这么说 可是我试验的结果却不是这样
而如果是轻量级组件则系统会自动调用repaint() 然后repaint()直接调用paint()  
于是我试了试, 代码如下:
Java code

import java.awt.*;

import javax.swing.*;

public class TestLib extends JFrame{
    public static void main(String[] args) {
        TestLib c = new TestLib();
        c.setSize(200,200);
        c.setVisible(true);
        
    }
    TestLib() {
        Component2 c = new Component2();
        
        getContentPane().add(c);
    }
}
class Component2 extends Button {
    public void update(Graphics g) {
        super.update(g);
        System.out.println("update!!");
    }
    public void paint(Graphics b) {
        super.paint(b);
        System.out.println("paint!!");
    }
    public void repaint() {
        super.repaint();
        System.out.println("repaint");
    }
}


可是测试结果是一开始只有paint!! 然后我用别的窗口遮住程序的窗口 然后再移开 还是出现一个paint!! 每次都这样 从来没有调用过repaint 这是为什么?
假如把Button改成JButton 结果是一出来就3个paint!! 这是为什么?

------解决方案--------------------
先看看这篇文章吧:
http://blog.csdn.net/yanghai0321/article/details/6916657
------解决方案--------------------
没仔细研究过,先看看2楼说的这篇文章
------解决方案--------------------
对于这个问题,我们分两步说

第一:repaint(),paint(), update()三者的调用关系

repaint() 方法:
根据 API 可以得知,
当前控件为轻量级控件时, repaint() 会调用该控件的 paint() 方法
(但是我从源码上没有看出来其有调用 paint,而是在递归的调用父控件的 repaint,从理论上说,这个过程必然会最终找到一个 Window 级的重要级控件)
当前控件为重量级控件时, repaint() 会调用该控的 update() 方法
(但是从源码上看,其是产生了一个 PaintEvent 事件,并派发至事件序列中,待线程去处理,这个处理的过程的代码貌似看不到,其具体是执行的 update() 方法,还是 paint() 方法也不得而知)

update()方法:
在 Component 类中,其单纯的调用了 paint(),至于 Component 的各个子孙类有无重写该方法,要一个个去看
但是根据观察,基本上没有几个类有重写这个方法,即便是重写的,也是一样单纯的调用了 paint() 方法

paint() 方法:
在 Component 类中,没有任何实现,应该是在 Component 的子孙类中各自实现的

这里就产生了一个问题:update()方法真的有被调用么?在哪里调用了?
从实验的结果看,这个方法无论什么时候似乎都没有被调用,
而且该方法的存在也很鸡肋
可有可无,单纯的调一下 paint(),还不如直接调用 paint() 呢
所以我在这里做一个大胆的假设,PaintEvent 派发至事件序列之后,处理时是直接调用了 paint() 方法,而没有调用 update 方法
这就和 API 的说明有冲突了,
可能是 Java 的开发人员觉得这是底层实现,实现他们已经改了,API 也懒得改了
也可能是和系统相关,我是在 windows 下测试的,不知道 linux 下有无变化
也可能是我实验没有做仔细,希望大家给点不同意见


第二:repaint() 是什么时候自动调用的?

重量级控件的话,我还真不知道是什么时候自动调用的,
从实验结果上看,似乎也没哪里自动调用这个方法了,

轻量级控件的话,
去看各个控件对应的 UI 类就知道了
UI 类中注册了大量的事件监听器
比如大小变化时、获得/失去焦点时、鼠标进入/移出时、等等
很多地方都显式调用了 repaint 方法
这就是自动调用 repaint 方法的来源了

所以 Button 我不能确定其会自动调用 repaint 方法
而 JButton 你想知道其什么时候会自动调用 repaint 方法,去看一下其对应的 UI 类(MetalButtonUI、BasicButtonUI)
------解决方案--------------------
我觉得吧,repaint()这个方法应该是程序员自己调用的吧,将repaint写在事件处理中,然后当事件触发时,系统再调用它。若是没有对事件进行监听的话,系统应该只会调用paint方法