Java Swing 应用编程接口提供了可插拔式外观风格(PLAF)的特性它允许Swing 图形用户接口(GUI)小应用根据编程人员定制的外观风格设置来改变界面外观风格
几乎所有现代用户接口框架都结合了视图和控制无论它们是基于SmallTalkC++或Java
Swing将每个组件的视图和控制封装到一个称为UI委托的对象中
因此Swing的体系结构被称为模型委托结构而不是模式视图控制器结构理想情况下模型和UI委托直接的通讯是间接的允许多个模型与一个UI委托相连反之亦然
UI委托
每个UI委托源自一个名为ComponentUI的抽象类ComponentUI的方法描述了一个UI委托和使用它的组件之间进行通讯的基本原理
注意的是每个方法都将JComponent作为一个参数ComponentUI有很多方法这里只给出几个最重要的
·static ComponentUI createUI(JComponent c)该方法通常用来返回UI委托的一个共享实例该UI委托通过定义ComponentUI子类本身而定义这个共享实例用于相同类型的组件之间的共享(例如所有使用金属外观的JButtons共享同样的静态UI委托实例默认情况下该委托实例在talMetalButtonUI中定义
·InstallUI(JComponent c)该方法在特定的组件上安装ComponentUI通常会给组件和它的模型添加一个监听器当状态发生改变时来通知UI委托进行视图的更新
·Update (Graphics g JComponent c)如果组件是不透明的那么应该描绘它的背景并调用paint(Graphics gJComponent C)方法
·Paint (Graphics g JComponent c):为了能够正确地描绘该方法要从组件收集所有需要的信息以及可能的模型
为了增强特定UI委托的使用我们可以调用一个组件的setUI()方法如下所示
JButton m_button = new JButton();
m_buttonsetUI((MyButtonUI)MyButtonUIcreateUI(m_button));
JComponent类中定义了用于分配UI委托的方法因为方法声明中不包含特定组件代码然而对数据模型而言这是不可能的因为不存在所有模型可以追溯到的基接口(例如不存在像Swing模型中的ComponentUI此类的基类)为此分配模型的方法在JComponent的子类中定义
使用PLAF
Swing包含几个UI委托集每个集合中包含了用于大部分Swing组件的ComponentUI实现且每个这样的集合称为一个PLAF实现
javaxswingplaf包有继承自ComponentUI的抽象类组成javaxswingplafbasic包中的类扩展了这些抽象类用来实现基本的外观UI委托集合是所有其它外观类用作构建自己的外观的基类基本外观不能自己使用因为BasicLookAndFeel是一个抽象类有三个继承自BasicLookAndFeel的可插拔式外观实现
·Windows: comsunjavaswingplafwindowsWindowsLookAndFeel
·CDEMotif: comsunjavaswingplafmotifMotifLookAndFeel
·Metal (default): talMetalLookAndFeel
同时还有一个模仿苹果用户接口的MacLookAndFeel但是没有包含在Java中必须单独下载多路外观javaxswingplafmultiMultiLookAndFeel扩展了javaxswingplaf中的所有抽象类它运行同时使用多种外观的组合且有意但并不仅限于和访问外观一起使用每个多路UI委托的任务是管理每个它们的子UI委托
每个外观包中都包含了一个继承自抽象类javaxswingLookAndFeelBasicLookAndFeel MetalLookAndFeel WindowsLookAndFeel等的类这是访问每个外观包的中心点当改变当前外观时你会用到它们同时UIManager类(用于管理安装的外观)使用它们来访问当前外观UIDefaults表(其中包含了用于每个Swing组件相应外观的UI委托类名称)
要想改变应用的当前外观你只需要简单调用UIManager的setLookAndFeel()方法并将要使用的外观全名传递给该方法即可可以使用列表A中的代码在运行时完成该任务
列表A try {
UIManagersetLookAndFeel(
comsunjavaswingplafmotifMotifLookAndFeel);
SwingUtilitiesupdateComponentTreeUI(myJFrame);
}
catch (Exception e) {
Systemerrprintln(Could not load LookAndFeel);
}
当外观改变时Swing实用工具updateComponentTreeUI()通知所有特定组件的孩子并通知它们丢弃原来的UI委托用来换取一个不同的特定类型委托
图AB和C演示了金属图形和窗口外观之间的不同之处
图A
图B
图C
创建一个PLAF
在创建一个PLAF之前你必须在Java中创建外观的两种设计方法中做出决定其中一种方法是通过扩展javaxswingplaf包来创建外观另一种方法是通过扩展已经存在的外观包通常是javaxswingplafbasic来实现
如果要创建一个用于PC的外观我们不推荐使用扩展来自javaxswingplaf包中的外观的方法这是因为javaxswingbasic包中已经扩展了几乎整个的javaxswingplaf包供我们使用这样我们可以通过挑选外观需要的东西来进行定制而不需要扩展和实现任何东西
javaxswingplaf包的实现遵循的一个基本原则是使得定制一个外观尽可能的简单这个原则是LookAndFeel类中组件颜色和UI类的中心
javaxswingplafbasic包以我们希望的方式描绘轻量级Swing组件如果你是为一台设备而不是计算机屏幕创建一个外观那么最好的方法是从零开始扩展javaxswingplaf包
Peter VMikhalenko是 Sun公司认证专业技术人员现为Deutsche银行业务顾问