Swing的体系结构被称为模型委托结构而不是模式-视图-控制器结构,Swing将每个组件(JComponent及其派生类)的视图和控制都封装到一个与其相对应的UI委托的对象之中(ComponentUI及其派生类的对象)。可插拔LAF的设计意味着实现组件展现(Look)和事件处理(Feel)的部分是被代理到独立的UI对象中的,这些UI对象是由当前的LAF提供的,它们可以被动态地修改。每个JComponent对象都有一个与其相对应的JComponentUI对象,例如与JButton相对应的UI delegate为ButtonUI,JSlider相对应的UI delegate为SliderUI,JComponent组件自身的绘制都是通过ComponentUI绘制的。
ComponentUI的方法描述了一个UI委托和使用它的组件之间进行通讯的基本原理。 下面给出了ComponentUI的几个重要方法:
◆staticComponentUI createUI(JComponent c):该方法通常用来返回UI委托的一个共享实例,该UI委托通过定义ComponentUI子类本身而定义。这个共享实例用于相同类型的组件之间的共享(例如,所有使用金属外观的JButtons共享同样的静态UI委托实例,默认情况下,该委托实例在javax.swing.plaf.metal.MetalButtonUI中定义。
◆InstallUI(JComponentc):该方法在特定的组件上安装ComponentUI。通常会给组件和它的模型添加一个监听器,当状态发生改变时来通知UI委托进行视图的更新。
◆Update(Graphics g, JComponent c):如果组件是不透明的,那么应该描绘它的背景并调用paint(Graphics g,JComponent C)方法。
◆Paint(Graphics g, JComponent c):为了能够正确地描绘,该方法要从组件收集所有需要的信息以及可能的模型。
下面详细叙述Swing类JComponent类通过UI绘制自身的过程:
窗口的绘制都是事件触发的,例如当窗口应用程序的启动,窗口的大小改变,窗口的平移,被覆盖部分重新恢复等都会触发窗口重绘,也就是调用JComponent或者其子类的paint()方法,这里需要注意,Container类负责管理所有的子窗口,例如JFrame窗口需要重绘时,它首先调用paintComponent()方法绘制自身,然后调用paintBorder()绘制边框,再调用paintChildren()方法绘制通过JComponent.add()方法放置在其上的组件。
下面我们来看下JComponent.paint()的介绍及其源代码:
This method actually delegates the work ofpainting to three protected me