笔者过去学习过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 <em>not</em> 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();
}
}
public NewToolBar(Shell parent, int style) {
super(parent, style);
new ToolItem(this, SWT.NULL);
}
}
以上是SWT和Swing代码的区别