当Java在1995年的春天***次发布的时候,它包含了一个叫AWT(Abstract Windowing Toolkit)的库,用来构建图形用户界面应用程序。Java很有雄心的宣言--"write once, run anywhere"许诺:一个具有下拉菜单,命令按钮,滚动条以及其他常见的GUI控件的应用程序将能够在各种操作系统上运行而不必重新编译成针对某一平台的二进制代码,包括Microsoft Windows, Sun’s own Solaris, Apple’s Mac OS以及Linux。
虽然最初Java是支持操作系统独立的应用程序开发,在Java提出"write once, run anywhere"宣言那段时间的革命导致了Java applet和主导桌面应用程序计划的产生。
尽管从那以后大部分构建桌面应用程序的成就都慢慢衰退,Java构建图形用户界面的能力反倒增强了。跟踪Java GUI的发展和演化,我们将发现3个主要的构建窗口程序库:AWT,Swing和SWT(Standard Widget Toolkit)。在这一章里我们将查看和分析这3个库中的每一个库,并且我们将一起来看一看第4个库--JFace。其实JFace不算一个真正的构建窗口程序库,而是在基于SWT之上的一个抽象层。
AWT
很多围绕着介绍Java技术的令人激动的地方都基于applets--一个可以让程序通过Internet发布并在浏览器内执行的新技术。用户和开发人员都热衷于斯,因为applets许诺将简化跨平台应用程序的开发,维护和发布,而这是商业软件开发中几个最富挑战性的话题。
为了方便用Java构建图形用户界面,Sun最初提供了一个在所有平台下具有的独特Java外观的图形界面库。Sun在applet技术策略方面的首要伙伴Netscape提出applets应该维持和运行时平台一样的外观。他们希望applets在某一平台下在显示和行为上能够像其他应用程序一样。
为了实现Netscape的"本地外观"的目标,在JDK的***个发布版中包含了AWT这个库。AWT的缺省实现使用了"对等"机制,即每一个Java GUI窗口部件都在底层的窗口系统中有一个对应的组件。
例如,每一个java.awt.Button对象将在底层窗口系统中创建一个唯一对应的button。当用户点击那个按钮的时候,事件将从本地实现库传送到Java虚拟机里,并且最终传送到与java.awt.Button对象相关联的逻辑。对等系统的实现以及Java组件与对等组件之间的交流的实现都隐藏在底层JVM实现中,Java语言级的代码仍然跨平台。
尽管如此,为了保持"write once, run anywhere"的许诺,Java不得不妥协和折衷。特别的,Java采用了"最小公分母"的方法,即AWT仅仅提供所有本地窗口系统都提供的特性。这就需要开发人员为更多高级特性开发他们自己的高级窗口部件,然后提供给用户不同的使用体验。
其他的问题也减缓了人们对applets的接受和承认。Applets运行在一个安全的"沙箱"里面并且能够阻止恶意的applets对文件系统,网络连接等资源的滥用。尽管沙箱提供了安全性,但它"阉割"了应用程序。毕竟一个应用程序不能运用一个网络连接来保存一个文件是不好的。Java GUI应用程序也不能像本地程序一样响应灵敏。这是在当前硬件平台和Java的解释性天性下预期结果。
所以,用AWT开发的应用程序既缺少流行GUI程序的许多特性,又不能达到在显示和行为上像用本地窗口构建库开发的程序一样的目标。应该有一个更好的库来让Java GUI取得成功。
Swing
于1997年JavaOne大会上提出并在1998年5月发布的JFC(Java Foundation Classes)包含了一个新的使用Java窗口开发包。这个新的GUI组件叫做Swing,感觉到它是对AWT的升级,并且看起来对Java占据计算机世界很有帮助。对Java来说已经万事具备了:可下载的applets将是未来的软件,人们将从其他操作系统转向JavaOS,从传统的计算机转向叫做JavaStation的瘦客户端网络计算机,Microsoft将最终因为不能在桌面程序领域与之想抗衡而被废黜。虽然这些景象从来没有实现,Swing作为Java applets和applications的GUI库倒确实十分繁荣。
Swing架构
尽管"Swing"仅仅是这个新组件的指代名称,它一直持续使用到今天。可能是因为这个名称太贴切了,Swing尝试着以以下几种方式改变公认的观点:
AWT依赖对等架构,用Java代码包装本地窗口部件,Swing却根本不使用本地代码和本地窗口部件
AWT把绘制屏幕交给本地窗口部件,Swing自己的组件绘制自己
因为Swing不依赖本地窗口部件,它可以抛弃AWT的最小公分母的方法并在每个平台下实现每个窗口部件,从而创建一个比AWT更强大的开发工具包
Swring缺省情况下采用本地平台的显示外观。然而,它并不仅仅限于此,而是还可以采用插件式的显示外观。因此Swing应用程序可以看起来想Windows应用程序,Motif应用程序,Mac应用程序甚至它自己的显示外观--"金属"。所以,Swing应用程序可以完全忽略它运行时所在的操作系统环境并且仅仅看起来像自己。这是单调一致的桌面应用程序外观的一大挑衅。想象一下Swing有多傲慢!
尽管如此,Swing组件超越了简单的窗口部件,它体现了正不断出现的设计模式以及一些***实践。采用Swing,你不仅仅得到GUI窗口部件的句柄和它所包含的数据,而是定义一个模型去保存数据,定义一个视图去显示数据,定义一个控制器去响应用户输入。事实上,大部分Swing组件的构建是基于MVC(model-view-controller)模式的。MVC使应用程序开发变得更清晰,更易维护和管理。
Swing的缺点
尽管Swing在AWT的基础上做出了巨大的改进,它仍然没能使Java作为构建桌面应用程序的工具。也许Swing的拥护者会立即举出Swing的成功应用案例,例如开源文本编辑器jEdit或者Borland的UML(Unified Modeling Language)建模工具Together,但是Swing应用程序仍然在桌面应用方面显得很少。Sun提出了一个记录可得到的Swing应用程序的列表"Swing Sightings"来证明Swing应用是值得注目的。然而我们也看到了"C++ Sightings"和"Visual Basic Sightings"的网页。
为什么Swing没有履行它的诺言?原因可能归结为下面两点:
速度的缺乏
界面外观
Swing的狂热者可能会对Swing速度慢这一点感到忿忿不平。不可否认,JIT(just-in-time)编译器,Java虚拟机以及Java语言本身就使得Swing应用程序和本地程序拉开了一定差距。尽管如此,Swing仍显得比本地应用程序行动缓慢和响应不积极。由于桌面计算变得越来越快,用户的速度期望值也随之增加,任何可感知的迟缓都将是无法忍受的。
对Swing的显示外观的问题的抱怨也引起了Swing的开发者的愤怒。毕竟他么宣称Swing拥有各种可插入式的外观,并且事实上可以显示成任何样子。J2SE 1.4.2 甚至添加了对Windows XP和GTK+的支持,以致于在这些平台下运行的Swing应用程序会自动采用该平台的外观。
尽管如此,问题仍然存在:Swing将一直处于***的图形用户界面的后面,因为必需在Java库里明确地添加对***GUI的支持。当使用J2SE 1.4.2 或更早的版本时在Windows XP上运行的Swing应用程序将显现为Windows 98的外观。而且,当使用XP themes或WindowBlinds等软件来改变皮肤或图形外观时用户日益铭记他们自己的特征和个性。而Swing不仅不理会操作系统,甚至连用户参数选择也不理会。
简短的说,Swing应用程序不像本地应用程序一样执行,外观也不一样。Java要想摆脱常年以来处于不断学习中的地位并掌握桌面应用程序开发中的众多角色,它的GUI仍需要改进。
SWT
当Eclipse.org社区人员开始构建Eclipse时,他们意识到Swing和AWT都不足以用来构建真实世界的商业程序。结果,他们决定构建一套新的GUI开发工具包用来显示Eclipse界面。这个工具包借用了VisualAge SmallTalk中的大量的库。他们把这个新的工具包命名为SWT(Standard Widget Toolkit).意识到本地行为需要本地窗口部件,SWT的设计者们采用了AWT的对等架构,而仅仅当本地组件不存在时(例如Motif下的树形组件)才求助于Java实现。这样,SWT吸收了AWT和Swing实现的***的部分:当可以得到本地组件时使用本地实现,当不能得到本地组件时使用Java实现。这就同时保证了与本地窗口部件相当的外观和响应度。
SWT于2001年与Eclipse IDE(Integrated Development Environment)一起集成发布。在这个最初发布版之后,SWT发展和演化为一个独立的版本。它可以使用与众多操作系统,包括Microsoft Windows,Mac OS X以及几种不同风格的Unix等。写作本书的这个时候,当前官方发布版本为2.1.3。3.0版为beta版,现在也可以下载。本系列文章采用SWT 3.0。
另一个重要的优势为SWT的源代码是在一个开源许可下免费可得并无病毒的。这就意味着你可以在你的应用程序中使用SWT并且在任何许可认证下发布它。源代码对理解SWT库的低级别功能性和调试应用程序都是很有帮助的。开源软件也意味着比商业发布软件更新的更加频繁。
JFace
JFace的构建基于SWT,它提供了SWT的功能和更简易的MVC模式。SWT使用直接的API提供了原生的窗口部件,例如,你创建一个table部件并且插入你想显示的行和列的数据。JFace则提供了在SWT基础之上的抽象层,所以你可以对抽象层编程然后抽象层与SWT API交互来替代直接对SWT API编程。考虑一下对本地C窗口部件接口编程同使用C++GUI类库的区别或是使用AWT与Swing的区别。这些类比将有助于阐述SWT与JFace的区别。例如,为了使用JFace中的table,你仍旧创建table窗口部件,但是你不向里面插入数据。反而,你将你的content(或model) provider类和你的display(或 view) provider类提供给它。接着,table调用你提供的类来决定数据内容和怎样显示数据内容。 JFace没有彻底地抽象SWT。即使在用JFace写的程序中也会常常出现SWT及它的低级API。在本文第二部分带领您构建正确的SWT基础之后,我们将在第三部分探究JFace的力量。
总结
从最开始Java就提供了构建跨平台的窗口GUI应用程序库,从AWT,Swing到现在的SWT和JFace。最初的工具包能力微弱,但是后来提供的工具包认识到之前工具包的缺点并取得了巨大的进步。SWT和JFace不仅使Java成为一个构建桌面应用程序的可行的选择,也使之成为一个具有优势的开发平台。尽管过去对得到轻便和强大的Java系统的尝试必然意味着接受它在GUI方面的缺点,如今这个不足已经不存在了,Java终于可以统领它在桌面计算应用方面的位置了。
【编辑推荐】