笔者过去学习过Swing(也算是AWT的增强版吧), 现在开始学习一下 SWT, 还没有开始深入 JFace 和 RCP, 一步步来吧。 先学好基础的, 又不用着急做项目用。 本文讨论的内容仅限于我已知的 SWT和Swing 范围, 希望能对有 Swing 经验的人快速了解 SWT 有所帮助。
第一个不同点就是 SWT 的类库结构不像 Swing, 没有单一的父组件。 SWT 中有好几个父类:
◆Widget —— 基本的 SWT GUI 组件(类似于 Java AWT 中的 Component 和 Swing 中的 JComponent)。Widget 是一个抽象类。
◆Control —— 拥有操作系统的对等物的窗口小部件(换句话说,在操作系统中具有同一身份)。Control 是一个抽象类。
◆Composite —— 包含其他控件的控件(类似于 Java AWT 中的 Container 和 Swing 中的 JPanel)。
◆Item —— 其他控件包含的窗口小部件(该控件可能不是复合控件),比如列表和表。注意,包含一些项的控件很少包含其他控件,反之亦然。Item 是一个抽象类。
SWT 的组件不能随意继承, 其源代码中会标注: IMPORTANT: This class is not intended to be subclassed.如果你那样做了, 运行的时候 SWT 系统就会报错, 也不能任意包含子组件。 某些组件, 例如 Tree, 只能接收 TreeItem 作为其子组件。 这样在写一些可重用的图形组件的时候必须注意, Swing 中的写法不能直接套用在 SWT 中。
Swing 的所有图形界面类都继承自 java.awt.Container, 这意味着所有的 Swing 组件都可以包含任意的子组件, 也可以被继承。 这是两个类库的第一个不同点。
第二个不同点就是 SWT 没有利用 Java 的自带垃圾收集功能来管理对象的销毁, 大部分对象都必须调用 dispose() 方可完成资源的释放。
第三个不同点就是在组件的显示上, SWT 抽象了一个 Display 对象来处理 SWT 和操作系统底层组件的通信, 资源申请释放, 事件循环, 任何显示的 SWT 组件必须有且仅有一个 Display 对象。
第四个不同点就是 Swing 的组件实现了 MVC 机制, 但是 SWT 没有(目前来看)提供 MVC 机制。 也就是说绝大多数 SWT 组件都是不可以更换显示的外观的, 我的意思是例如像皮肤这样的机制, 例如:实现一个 Office 2003 外观的橙色菜单条的显示, SWT 是不能通过简单的编码来实现的(也许有, 但是还没找到相关的资料)。
SWT 的每个组件对象提供了 setData(Object) 这样的方法来给组件存储一个或者多个数据对象, Swing 中没有类似的概念。
第五个不同点就是绝大多数的 SWT 组件创建的时候都必须指定父组件和风格属性, 也就是必须有一个 parent 对象, 也不能运行的时候动态变更父组件, 具体例如 Menu 对象里有 Decorations getParent () , 但是并无对应的 setParent() 方法。 组件创建之后即自动加入父组件成为其一员, 这和 Swing 的必须通过 add() 方法来加入父组件是不一样的。 大多数的 SWT 组件不提供无参数的构造器, 这就意味这他们不是 JavaBean, 这点上 Swing 的绝大多数组件都是 JavaBean.
总结以上这些内容我们可以感觉到 SWT 更像是操作系统本地组件的一种封装, 而不是基于 Java OO 的概念对其进行映射, 其优点就是数据结构简单。
好了, 接下来还是通过一些SWT和Swing的代码来比较吧。第一个是经典的 Hello World
SWT 版本
import org.eclipse.swt.widgets.*;
public class SWTHelloWorld {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Hello World!");
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Swing 版本
import javax.swing.JFrame;
public class SwingHelloWorld {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("Hello World!");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
}
SWT 的 Text 属性在不同的组件中有不同的意思, 对于窗体来说它是标题, 对于控件来说它是显示的文本, Swing 中这个是分开的, 对于窗口来说是 Title 属性, 对于控件来说是 Text 属性。 SWT 的事件循环基于显式的 while 模式, 而 Swing 已经在底层封装好了事件的循环和处理。 所以这两段代码最明显的不同就是 SWT 多了时间循环的部分, 即文中粗体的部分。
接着我们来看看继承 SWT 的组件会有什么后果。 在 Swing 中继承一个组件然后向其中添加子组件, 例如建立一个自定义的工具栏, 然后向其中加入子栏目, 并最后显示出来, 这是经常进行的操作, 再看看 SWT 中:
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.SWT;
public class NewToolBar extends org.eclipse.swt.widgets.ToolBar {
public static void main(String[] args) {
try {
Display display = Display.getDefault();
Shell shell = new Shell(display);
new NewToolBar(shell, SWT.NULL);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Swing与SWT的比较
基于以前的文章,本文Swing和SWT的方方面面做一个简短的比较。它们的优劣点在前面的文章中都曾详细讲述过,这儿只是简单罗列出来,不再做详细论证。你可以参看前面的文章,对照这些比较。对于一些观点性的比较,比如后面的体验和感受则纯粹是我个人的想法。
简短的说Swing相对于SWT的优势有:速度快、有皮肤机制支持、优秀的框架、灵活可扩展、官方标准、47%的市场占有率、丰富的第三方类库、不计其数的学习材料、强大免费的图形界面设计工具(NetBeans Matisse)。相对于SWT的缺点有:多耗10M左右内存、启动速度稍慢、桌面集成相对弱。两者都有着漂亮的本地化外观。这些内容我们在前面的文章中都连篇累牍的介绍过。
从两者当初设计的目标来看,SWT是治标,目的是为了提高速度、改善外观;Swing是治本,它从框架、结构着手。Swing因此有着比SWT更广阔的发展空间。由于有着优秀的架构,而且Java完全控制着实现权,所以Swing总是可以不断被改进的。当Swing成熟了而弥补了速度和外观后,Swing的发展就因其良好的架构,就因为代码控制权等因素,而呈现出一片广阔的天空。而SWT从一诞生起,其先天性架构和实现缺陷就已经决定它很难前进。由于依赖本地操作系统,SWT可以发展的空间很小。开始也许可以借助操作系统的本地实现来快速达到很好的效果,但到此就结束了,自己再优化反展的空间就很小了。它将的实现大部分都交给了异质的系统,它无法控制的系统,却需要花费相当代价进行交互的系统。
SWT上手速度要快一些。因为SWT的API类似于传统的GUI工具,这使得许多从传统GUI工具中转过来的程序员很容易上手。传统GUI工具系统尤其是Windows平台的,是基于消息映射机制的,其基本模型是面向过程和面向消息的。Swing的设计思想是基于面向对象的典范,其MVC模式是程序设计模式的经典。总的来说,Swing之于SWT就像面向对象语言之于面向过程语言。但就学习曲线来说,Swing并不比SWT陡峭。Swing本身已经非常成熟,官方提供的文档,各种网上资料、书籍、讨论区浩如烟海,其实学习曲线也未必比SWT陡峭。
就Swing与SWT的开发体验来说,SWT给开发者的体验往往是对于SWT的满意程度同使用SWT的时间成反比,同对SWT和Swing的了解程度成反比。刚开始往往是非常满意,甚至有惊艳的感觉。但随着使用时间的增长,随着对于SWT了解的深入,这种满意度就会越来越下降。总之喜爱程度和了解程度成反比。Swing给开发者的体验是。开始也许你要经常发牢骚,这些牢骚就像在抱怨一个饱经风霜、看似相貌平平、但实际却非常有内涵的人一样。随着你对它的了解的加深,你就会越来越被它吸引,最终你会惊叹于它的博大精深。你会发现你越学懂得越少,而你的知识和能力却像内力一样越来越深厚。总之喜爱程度和了解程度成正比。
对我来说,Swing和SWT之间的故事就像是火车与马车之间的故事:火车刚发明的时候,许多人嘲笑火车的速度太慢、太丑陋。火车在第一次试跑的时候,人们坐着华丽的马车和火车比赛,结果很容易就超过了火车。于是人们都在嘲笑这个丑陋、笨重而缓慢的家伙,却看不到火车的本质和潜力。几百年后,火车的速度已经超过一百多公里,运输力已经达到成千上万吨,火车已经成为现在交通的主干力量,而马车仍然在徘徊在当初。为什么呢?就因为火车的本质架构是好的;就因为火车有着很大改进空间;就因为火车设计之初的目标是远大的,不是运几百斤东西就满足了的,而是为更高速度、更大运力铺好了基础架构。
public NewToolBar(Shell parent, int style) {
super(parent, style);
new ToolItem(this, SWT.NULL);
}
}