Swing组件的paint方法的处理流程

开发 后端
本文介绍Swing组件的paint方法的处理流程,Swing组件的paint方法是内部接口方法,一般用户不要直接调用这个方法,它总是在事件调度线程中调用。

昨晚回去后还是觉得Component对象本身说的太简单,想来想去,觉得内容实在是太多,有必要补充两个续文说明Component的其它概念。今天介绍Swing组件paint方法的处理流程,这个流程能使我们理解许多Swing机制。

Swing组件的paint方法是内部接口方法,一般用户不要直接调用这个方法,它总是在事件调度线程中调用。一般说来除了系统刷新事件触发这个方法, Component的repaint也触发这个方法的调用。repaint方法常用于当组件状态发生变化时刷新界面使用。repaint方法是Swing 中少数几个线程安全的方法,可以在任何线程中调用它。它的原理是往事件队列中post一个PAINT事件。由于事件队列的事件是被事件调度线程同步执行的,所以这个方法总是线程安全的。事件调度线程从PAINT事件中获取事件源组件,从系统申请到图形设备资源后,调用该组件的update方法。 update是AWT时代遗留下来的产物,本意是AWT组件画好组件背景后,再调用paint方法画出组件的前景。Swing出现后这个方法就被弃用了,所有逻辑都转到paint方法里。Update只是简单地调用paint方法来完成组件的渲染。老的Java教材上经常可以看到,所谓repaint调度 update方法,update接着调用paint方法,自定义组件需要重载paint方法等话语,就是因为这个历史造成的。

现在JComponent的实现已经把paint方法改造成可以嵌套多重机制地方,这些机制包括层次渲染、边框、透明背景、双缓冲以及皮肤等。这些机制分别实现不同目的的组件提供了方便。

图形用户界面的组件按照其在组件树上的角色可以分为容器组件和叶组件。Swing模型把叶组件当作是特殊、没有子组件的容器组件,只是JComponent继承Container类,所有Swing组件继承JComponent的原因。

JComponent在paint方法中首先根据组件是否需要使用双缓冲,封装好图形设备对象,然后经过一番处理后调用paintComponent方法画出自身,然后调用paintBorder画出边框,最后调用paintChildren来完成子组件的渲染。

paintComponent意思是画出组件自身,不包括子组件。因此前一文章中的MyButton可以通过覆盖paintComponent方法来完成 MyButton的重画。在JComponent实现中,JDK 6的paintComponent的代码为:

  1. protectedvoidpaintComponent(Graphicsg){  
  2. if(ui!=null){  
  3. GraphicsscratchGraphics=(g==null)?null:g.create();  
  4. try{  
  5. ui.update(scratchGraphics,this);  
  6. }  
  7. finally{  
  8. scratchGraphics.dispose();  
  9. }  
  10. }  

可以看出,背景透明机制在这儿实现。首先UI Delegate对象判断Component是否背景透明的,如果不是透明的,则使用背景色填充整个Component区域,然后调用paint(g, c)来完成组件在这种LookAndFeel种的渲染。了解了这些后,我们几乎就明白了Swing如何实现背景透明和如何切换皮肤。由于后面的文章还会对 UI Delegate和皮肤机制详细描述,这儿就到此为止。

目前还不要求实现皮肤,在这种情况下只需要重载paintComponent方法就行了,如果需要背景透明机制,可以模仿上面代码,MyButton的paintComponent可以这样写:

  1. publicvoidpaintComponent(Graphicsg){  
  2. if(isOpaque()){  
  3. g.setColor(getBackground());  
  4. g.fillRect(0,0,getWidth(),getHeight());  
  5. }  
  6. if(pressed){//按钮按下去了  
  7. //画出按下的样子  
  8. }else{  
  9. //画出抬起的样子  
  10. }  


paintChildren完成容器类组件的子组件的渲染。JDK缺省的实现是调用各个自组件的paint方法。一般来说不需要重载这个方法。如果想改变诸如组件Z-order遮挡顺序,可以覆盖这个方法,从相反顺序调用组件的paint方法。

到这儿我们对Swing的结构有了更深化的理解,UI Delegate机制也已经初露倪端。还有几个重要Swing Component概念或者机制没有讲,明天的续文再对它们做出说明。

【编辑推荐】

  1. 概述Swing窗体的种类
  2. 浅谈Swing线程三种
  3. Swing全屏幕模式
  4. 浅析Swing线程中的LookupEvent
  5. Swing文件选择器的制作
责任编辑:佚名 来源: 百度空间
相关推荐

2009-07-10 09:38:06

Java swing组

2009-07-15 11:02:32

Swing组件

2009-07-14 17:21:42

Swing组件

2009-07-10 11:45:44

Java Swing

2009-07-10 16:29:32

Swing组件

2009-07-10 10:19:57

JFormattedTSwing

2009-07-10 13:20:37

Swing容器组件

2009-07-10 14:58:13

JLabel组件JFC和Swing

2009-07-15 10:52:13

JTree组件

2009-07-10 10:08:59

Spinner ModSwing组件

2009-07-15 13:06:38

Swing组件

2009-07-16 10:11:06

渲染器RendererSwing组件

2009-07-10 18:06:59

JTree Swing

2009-07-17 12:54:13

2009-06-09 16:53:22

Java Swing处理方法比较

2009-07-15 16:29:41

Swing绘画

2009-07-15 10:06:54

Swing实现MDI

2009-07-16 11:19:48

外部线程Swing组件

2009-07-17 14:38:51

轻量级Swing组件

2009-07-14 18:05:28

轻量级Swing组件
点赞
收藏

51CTO技术栈公众号