GUI开发之AWT、SWING、SWT和JFACE的比较



AWT

Abstract Windows Toolkit(AWT)是最原始的 Java GUI 工具包。在任何一个 Java 运行环境中都可以使用它。

AWT 是一个非常简单的具有有限 GUI 组件、布局管理器和事件的工具包.有些经常使用的组件,例如表、树、进度条等,都不支持。

 

通常对于 AWT 来说(也适用于 Swing 和 SWT),每个事件类型都有一个相关的 XxxListener 接口(XxxAdapter 的实现可能为空),其中 Xxx 是去掉 Event 后缀的事件名(例如,KeyEvent 事件的接口是 KeyListener),用来把事件传递给处理程序。应用程序会为自己感兴趣处理的事件的事件源(GUI 组件或部件)进行注册。有时监听接口要处理多个事件。

 

AWT 的一个很好的特性是它通常可以对 GUI 组件自动进行销毁。这意味着您几乎不需要对组件进行销毁。一个例外是高级组件,例如对话框和框架。如果您创建了耗费大量主机资源的资源,就需要手动对其进行销毁。

 

AWT 组件是 “线程安全的(thread-safe)”,这意味着我们不需要关心在应用程序中是哪一个线程对 GUI 进行了更新。这个特性可以减少很多 GUI 更新的问题,不过使 AWT GUI 运行的速度更慢了。

 

AWT 让我们可以以自顶向下(top-down) 或自底向上(bottom-up) 或以任意组合顺序来构建 GUI。自顶向下的意思是在创建子组件之前首先创建容器组件;自底向上的意思是在创建容器(或父)组件之前创建子组件。在后一种情况中,组件的存在并不依赖于父容器,其父容器可以随时改变。

 

由于 AWT 要依赖于主机 GUI 的对等体(peer)控件(其中每个 AWT 组件都有一个并行的主机控件或者对等体)来实现这个 GUI,这个 GUI 的外观和行为(这一点更重要)在不同的主机上会有所不同。这会导致出现 “编写一次随处测试(write once, test everywhere,即 WOTE)” 的情况,这样就远远不能满足我们的要求了。

 

AWT 提供了一个丰富的图形环境,尤其是在 Java V1.2 及其以后版本中更是如此。通过 Graphics2D 对象和 Java2D、Java3D 服务,我们可以创建很多功能强大的图形应用程序,例如画图和制表包;结合使用 JavaSound,我们还可以创建非常有竞争力的交互式游戏。

 

 

Swing

Java Swing 是 Java Foundation Classes(JFC)的一部分,它是试图解决 AWT 缺点的一个尝试。在 Swing 中,Sun 开发了一个经过仔细设计的、灵活而强大的 GUI 工具包。

Swing 是在 AWT 组件基础上构建的。

 

为了克服在不同主机上行为也会不同的缺点,Swing 将对主机控件的依赖性降至了最低。实际上,Swing 只为诸如窗口和框架之类的顶层 组件使用对等体。大部分组件(JComponent 及其子类)都是使用纯 Java 代码来模拟的。这意味着 Swing 天生就可以在所有主机之间很好地进行移植。因此,Swing 通常看起来并不像是本地程序。实际上,它有很多外观,有些模拟(尽管通常并不精确)不同主机的外观,有些则提供了独特的外观。

 

Swing 对基于对等体的组件使用的术语是重量级(heavyweight),对于模拟的组件使用的术语是轻量级(lightweight)。实际上,Swing 可以支持在一个 GUI 中混合使用重量级组件和轻量级组件,例如在一个 JContainer 中混合使用 AWT 和 Swing 控件,但是如果组件产生了重叠,就必须注意绘制这些控件的顺序。

 

Swing 无法充分利用硬件 GUI 加速器和专用主机 GUI 操作的优点。结果是 Swing 应用程序可能比本地 GUI 的程序运行速度都慢。Sun 花费了大量的精力来改进最近版本的 Swing (Java V1.4 和 1.5)的性能,这种缺点正在变得日益微弱。由于 Swing 的设计更加健壮,因此其代码基础也更坚实。这意味着它可以在一台健壮的机器上比 AWT 和 SWT 上运行得更好。

 

与 AWT 一样,Swing 可以支持 GUI 组件的自动销毁。Swing 还可以支持 AWT 的自底向上和自顶向下的构建方法。

 

与 AWT 不同,Swing 组件不是线程安全的,这意味着您需要关心在应用程序中是哪个线程在更新 GUI。如果在使用线程时出现了错误,就可能会出现不可预测的行为,包括用户界面故障。有一些工具可以帮助管理线程的问题。

 

与 AWT 类似,Swing 的一个优点是,它也是 Java 技术的一种标准配置。这意味着您不需要自己来安装它了。不幸的是,Swing 已经有了很大的变化,因此它很容易变得依赖于最新版本的 Java 语言所提供的特性,这可能会强制用户更新自己的 Java 运行时环境。

 

 

SWT

与 AWT 的概念相比,SWT 是一个低级的 GUI 工具包。JFace 是一组用来简化使用 SWT 构建 GUI 的增强组件和工具服务。SWT 的构建者从 AWT 和 Swing 实现中学习了很多经验,他们试图构建一个集二者优点于一体而没有二者的缺点的系统。从很多方面来说,他们已经成功了。

 

SWT 也是基于一个对等体实现的,在这一点上它与 AWT 非常类似。它克服了 AWT 所面临的 LCD 的问题,方法如下:定义了一组控件,它们可以用来构建大部分办公应用程序或开发者工具,然后可以按照逐个主机的原则,为特定主机所没有提供的控件创建模拟控件(这与 Swing 类似)。对于大部分现代主机来说,几乎所有的控件都是基于本地对等体的。这意味着基于 SWT 的 GUI 既具有主机外观,又具有主机的性能。这样就避免了使用 AWT 和 Swing 而引起的大部分问题。特定的主机具有一些低级功能控件,因此 SWT 提供了扩充(通常是模拟的)版本(通常使用 “C” 作为名字中的第一个字母),从而可以产生更一致的行为。

 

在对等体工作方式上,SWT 与 AWT 不同。在 SWT 中,对等体只是主机控件上的一些封装程序而已。在 AWT 中,对等体可以提供服务来最小化主机之间的差异(就是在这里,AWT 碰到了很多行为不一致的问题)。这意味着 SWT 应用程序实际上就是一个主机应用程序,它必然会全部继承主机的优点和缺点。这还意味着 SWT 不能完全实现 WORE 的目标;它更像是一种 WOTE 解决方案。这就是说,SWT 尽管不如 Swing 那么优秀,但是它在创建可移植解决方案方面是很杰出的。

 

SWT 不支持 GUI 控件的自动销毁。这意味着我们必须显式地销毁所创建的任何控件和资源,例如颜色和字体,而不能利用 API 调用来实现这种功能。这种工作从某种程度上来说得到了简化,因为容器控制了其子控件的自动销毁功能。

 

使用 SWT 只能自顶向下地构建 GUI。因此,如果没有父容器,子控件也就不存在了;通常父容器都不能在以后任意改变。这种方法不如 AWT/Swing 灵活。控件是在创建时被添加到父容器中的,在销毁时被从父容器中删除的。而且 SWT 对于 style 位的使用只会在构建时进行,这限制了有些 GUI 控件的灵活性。有些风格只是一些提示性的,它们在所有平台上的行为可能并不完全相同。

 

与 Swing 类似,SWT 组件也不是线程安全的,这意味着您必须要关心在应用程序中是哪个线程对 GUI 进行了更新。如果在使用线程时发生了错误,就会抛出异常。我认为这比不确定的 Swing 方法要好。有一些工具可以帮助管理线程的问题。

 

如果所支持的操作系统提供了可访问性服务,那么 SWT GUI 通常也就具有很好的可访问性。当默认信息不够时,SWT 为程序员提供了一个基本的 API 来指定可访问性信息。

 

SWT 提供了一个有限的图形环境。到目前为止,它对于 Java2D 和 Java3D 的支持还不怎么好。Eclipse 使用一个名为 Draw2D 的组件提供了另外一种单独的图形编辑框架(Graphical Editing Framework,GEF),它可以用来创建一些绘图应用程序,例如 UML 建模工具。不幸的是,GEF 难以单独(即在整个 Eclipse 环境之外)使用。

 

与 AWT 和 Swing 不同,SWT 和 JFace 并不是 Java 技术的标准配置。它们必须单独进行安装,这可以当作是 Eclipse 安装的一部分,也可以当作是单独的库进行安装。Eclipse 小组已经使它的安装变得非常简单,并且 SWT 可以与 Eclipse 分开单独运行。所需要的 Java 档案文件(JAR)和动态链接库(DLL)以及 UNIX® 和 Macintosh 上使用的类似库可以从 Eclipse Web 站点上单独下载。JFace 库需要您下载所有的 Eclipse 文件,并拷贝所需要的 JAR 文件。在下载所需要的文件之后,我们还需要将这些 JAR 文件放到 Java CLASSPATH 中,并将 DLL 文件放到系统 PATH 中。

 

SWT本身仅仅是Eclipse组织为了开发Eclipse IDE环境所编写的一组底层图形界面 API。或许是无心插柳,或是有意为之,至今为止,SWT无论是在性能和外观上,都超越了SUN公司提供的AWT和SWING。目前Eclipse IDE已经开发到了2.1版本,SWT已经十分稳定。这里指的稳定应该包含两层意思:

 

一是指性能上的稳定,其中的关键是源于SWT的设计理念。SWT最大化了操作系统的图形构件API,就是说只要操作系统提供了相应图形的构件,那么SWT只是简单应用JNI技术调用它们,只有那些操作系统中不提供的构件,SWT才自己去做一个模拟的实现。可以看出SWT的性能上的稳定大多时候取决于相应操作系统图形构件的稳定性。

 

另一个稳定是指SWT API包中的类、方法的名称和结构已经少有改变,程序员不用担心由于Eclipse组织开发进度很快(Eclipse IDE每天都会有一个Nightly版本的发布),而导致自己的程序代码变化过大。从一个版本的SWT更新至另一版本,通常只需要简单将SWT包换掉就可以了。

 

SWT采用了一种简单而直接的方式去适应本地GUI系统对线程的要求:在SWT中,通常存在一个被称为"用户线程"的唯一线程,只有在这个线程中才能调用对构件或某些图形API的访问操作。如果在非用户线程中程序直接调用这些访问操作,那么SWTExcepiton异常会被抛出。但是SWT也在*.widget.Display类中提供了两个方法可以间接的在非用户线程的进行图形构件的访问操作,这是通过的syncExec(Runnable)和asyncExec(Runnable)这两个方法去实现的。

 

 

JFace

JFace与SWT的关系好比Microsoft的MFC与SDK的关系,JFace是基于SWT开发,其API比SWT更加易于使用,但功能却没SWT来的直接。比如下面的代码应用JFace中的MessageDialog打开一个警告对话框:

 

MessageDialog.openWarning(parent," Warning"," Warning message");

 

如果只用SWT完成以上功能,语句不会少于30行!

 

JFace原本是为更加方便的使用SWT而编写的一组API,其主要目的是为了开发Eclipse IDE环境,而不是为了应用到其它的独立应用程序。因此在Eclipse 2.1版本之前,很难将JFace API完整的从Eclipse的内核API中剥离出来,总是要多多少少导入一些非JFace以外的Eclipse核心代码类或接口才能得到一个没有任何编译错误的JFace开发包。但目前Eclipse组织似乎已经逐渐意识到了JFace在开发独立应用程序起到的重要作用,在正在开发的2.1版本中,JFace也开始变成了和SWT一样的完整独立的开发包,只是这个开发包还在变动中(笔者写本文时,应用的Eclipse2.1M3版本)。JFace开发包的包前缀是以org.eclipse.jface开头。JAR包和源代码也和SWT一样,也在${你的eclipse安装路径}/plugins路径下去找。

 

对开发人员来说,在开发一个图形构件的时候,比较好的方式是先到JFace包去找一找,看是不是有更简洁的实现方法,如果没有再用SWT包去自己实现。比如JFace为对话框提供了很好的支持,除了各种类型的对话框(比如上面用的MessageDialog,或是带有Title栏的对话框),如要实现一个自定义的对话框也最好从JFace中的Dialog类继承,而不是从SWT中的*.widget.Dialog继承。

 

应用JFace中的Preference包中的类很容易为自己的软件做出一个很专业的配置对话框。对于Tree、Table等图形构件,它们在显示的同时也要和数据关联,例如Table中显示的数据,在JFace中的View包中为此类构件提供了Model-View方式的编程方法,这种方法使显示与数据分开,更加利于开发与维护。JFace中提供最多的功能就是对文本内容的处理。可以在org.eclipse.jface.text.*包中找到数十个与文本处理相关类。

你可能感兴趣的:(eclipse,swing,SWT,awt,jface)