1
SWT简介
从Java诞生至今,已经在太多的领域取得成功,然而它却很少在图形界面程序上崭露头角。究其原因,
Java语言缺省的图形界面开发包AWT和SWING实在是难脱其究,无论速度和外观,它们都难以让人接
受。如今,Eclip组织编写的SWT开发包,为Java程序员提供了AWT和SWING之外的一个更佳的选
择。在本文中,对SWT做了简单但尽可能全面的介绍。
Java语言的声望和它在桌面应用程序(GUI程序)所取得的成就显然极不相符,至今仍然很少能看到非
常成功Java桌面程序。虽然有JBuilder,Netbean,JProbe等大型软件作为代表,但这仍不能证明Java的
GUI程序是成功的:它们的外观总是和同一操作系统平台下的其它软件显得格格不入。对机器配置的需
求也似乎永无止境,这使得它们只能被一些总是拥有当前最高性能PC的程序员们所容忍,或是那些不在
乎金钱和时间的专业用户所接受。对绝大多数计算机使用者来说,AWT或SWING代表着怪异的界面和
无法接受的速度。StandardWidgetToolkit(SWT)或许是Java这一噩梦的终结者,广大Java程序员终于
可以开发出高效率的GUI程序,它们拥有标准的外观,几乎没有人能看出你的程序是用Java写出来的,
更为重要的是,这些程序是跨平台的。
SWT本身仅仅是Eclip组织为了开发EclipIDE环境所编写的一组底层图形界面API。或许是无心插
柳,或是有意为之,至今为止,SWT无论是在性能和外观上,都超越了SUN公司提供的AWT和SWING。
目前EclipIDE已经开发到了2.1版本,SWT已经十分稳定。这里指的稳定应该包含两层意思:
一是指性能上的稳定,其中的关键是源于SWT的设计理念。SWT最大化了操作系统的图形构件API,就
是说只要操作系统提供了相应图形的构件,那么SWT只是简单应用JNI技术调用它们,只有那些操作系
统中不提供的构件,SWT才自己去做一个模拟的实现。可以看出SWT性能上的稳定大多时候取决于相
应操作系统图形构件的稳定性。
另一个稳定是指SWTAPI包中的类、方法的名称和结构已经少有改变,程序员不用担心由于Eclip组织
开发进度很快(EclipIDE每天都会有一个Nightly版本的发布),而导致自己的程序代码变化过大。从
一个版本的SWT更新至另一版本,通常只需要简单将SWT包换掉就可以了。
第一个SWT程序
下面让我们开始一个SWT程序。(注意:以下的例子和说明主要针对Windows平台,其它的操作系统应
该大同小异)。首先要在Eclip安装文件中找到SWT包,Eclip组织并不提供单独的SWT包下载,必
须下载完整的Eclip开发环境才能得到SWT包。SWT是作为Eclip开发环境的一个插件形式存在,
可以在${你的eclip安装路径}plugins路径下的众多子目录下去搜索文件,在找到的JAR
文件中包含了SWT全部的Java类文件。因为SWT应用了JNI技术,因此同时也要找到相对应的JNI本
地化库文件,由于版本和操作平台的不同,本地化库文件的名称会有些差别,比如
是Window平台下EclipBuild2116的动态库,而在Unix平台相应版本的库文件的扩展名应该是.so,等
等。注意的是,Eclip是一个开放源代码的项目,因此你也可以在这些目录中找到SWT的源代码,相信
这会对开发很有帮助。
2
下面是一段打开空窗口的代码(只有main方法)。
e;
publicclassOpenShell{
publicstaticvoidmain(String[]args){
Displaydisplay=newDisplay();
Shellshell=newShell(display);
();
//开始事件处理循环,直到用户关闭窗口
while(!od()){
if(!dDispatch())
();
}
e();
}
}
确信在CLASSPATH中包括了文件,先用Javac编译例子程序。编译无错后可运行java
-=${你的SWT本地库文件所在路径}ell,比如
件所在的路径是C:swtlib,运行的命令应该是=c:swtlib
ell。成功运行后,系统会打开了一个空的窗口。
剖析SWTAPI
下面再让我们进一步分析SWTAPI的组成。所有的SWT类都用做为包的前缀,下面为了
简化说明,我们用*号代表前缀,比如*.widgets包,代表的是s包。
我们最常用的图形构件基本都被包括在*.widgets包中,比如Button,Combo,Text,Label,Sash,Table
等等。其中两个最重要的构件当数Shell和Composite。Shell相当于应用程序的主窗口框架,上面的例子
代码中就是应用Shell构件打开一个空窗口。Composite相当于SWING中的Panel对象,充当着构件容器
的角色,当我们想在一个窗口中加入一些构件时,最好到使用Composite作为其它构件的容器,然后再去
*.layout包找出一种合适的布局方式。SWT对构件的布局也采用了SWING或AWT中Layout和LayoutData
结合的方式,在*.layout包中可以找到四种Layout和与它们相对应的布局结构对象(LayoutData)。在
*.custom包中,包含了对一些基本图形构件的扩展,比如其中的CLabel,就是对标准Label构件的扩展,
上面可以同时加入文字和图片,也可以加边框。StyledText是Text构件的扩展,它提供了丰富的文本功能,
比如对某段文字的背景色、前景色或字体的设置。在*.custom包中也可找到一个新的StackLayout布局方
式。
SWT对用户操作的响应,比如鼠标或键盘事件,也是采用了AWT和SWING中的Obrver模式,在*.event
3
包中可以找到事件监听的Listener接口和相应的事件对象,例如常用的鼠标事件监听接口MouListener,
MouMoveListener和MouTrackListener,及对应的事件对象MouEvent。
*.graphics包中可以找到针对图片、光标、字体或绘图的API。比如可通过Image类调用系统中不同类型
的图片文件。通过GC类实现对图片、构件或显示器的绘图功能。
对不同平台,Eclip还开发了一些富有针对性的API。例如,在Windows平台,可以通过*.32包
很容易的调用ole控件,这使Java程序内嵌IE浏览器或Word、Excel等程序成为可能!
要进一步了解SWT的情况,可以在EclipIDE的帮助文档中找到SWT的JavaDoc说明。当然最深入的
了解莫过于去读SWT的源代码,这也正是开放源代码项目对程序员的魅力所在!
下面让我们展示一个比上面例子更加复杂一些的程序。这个程序拥有一个文本框和一个按键,当用户点
击按键的时候,文本框显示一句欢迎信息。
为了文本框和按键有比较合理的大小和布局,这里采用了GradLayout布局方式。这种布局是SWT中最
常用也是最强大的布局方式,几乎所有的格式都可能通过GradLayout去达到。下面的程序也涉及到了如
何应用系统资源(Color),以及如何释放系统资源。
privatevoidinitShell(Shellshell){
//为Shell设置布局对象
GridLayoutgShellLay=newGridLayout();
out(gShellLay);
//构造一个Composite构件作为文本框和按键的容器
Compositepanel=newComposite(shell,);
//为Panel指定一个布局结构对象。这里让Panel尽可能的占满Shell,也就是全部
应用程序窗口的空间。
GridDatagPanelData=new
GridData(_HORIZONTAL|_VERTICAL|_BO
TH);
outData(gPanelData);
//为Panel也设置一个布局对象。文本框和按键将按这个布局对象来显示。
GridLayoutgPanelLay=newGridLayout();
out(gPanelLay);
//为Panel生成一个背景色
finalColorbkColor=newColor(rent(),200,0,200);
kground(bkColor);
//生成文本框
finalTexttext=newText(panel,|);
//为文本框指定一个布局结构对象,这里让文本框尽可能的占满Panel的空间。
4
GridDatagTextData=new
GridData(_HORIZONTAL|_VERTICAL|_BOTH);
outData(gTextData);
//生成按键
Buttonbutt=newButton(panel,);
t("Push");
//为按键指定鼠标事件
Listener(newMouAdapter(){
publicvoidmouDown(MouEvente){
//当用户点击按键的时候,显示信息
t("HelloSWT");
}
});
//当主窗口关闭时,会触发DispoListener。这里用来释放Panel的背景色。
poListener(newDispoListener(){
publicvoidwidgetDispod(DispoEvente){
e();
}
});
}
把这段代码中的方法initShell()加入到第一个打开空窗口的例子中,得到的是一段能成功运行的完整GUI
应用程序。运行方法可参考第一个例子。
系统资源的管理
在一个图形化的操作系统中开发程序,都要调用系统中的资源,如图片、字体、颜色等。通常这些资源
都是有限的,程序员务必非常小心的使用这些资源:当不再使用它们时,就请尽快释放,不然操作系统
迟早会油尽灯枯,不得不重新启动,更严重的会导致系统崩溃。
SWT是用Java开发的,Java语言本身的一大优势就是JVM的“垃圾回收机制”,程序员通常不用理会变
量的释放,内存的回收等问题。那么对SWT而言,系统资源的操作是不是也是如此?答案是一个坏消息,
一个好消息。
坏消息是SWT并没采用JVM的垃圾回收机制去处理操作系统的资源回收问题,一个关键的因素是因为
JVM的垃圾回收机制是不可控的,也就是说程序员不能知道,也不可能做到在某一时刻让JVM回收资源!
这对系统资源的处理是致命的,试想你的程序希望在一个循环语句中去查看数万张图片,常规的处理方
式是每次调入一张,查看,然后就立即释放该图片资源,而后在循环调入下一张图片,这对操作系统而
言,任何时刻程序占用的仅仅是一张图片的资源。但如果这个过程完全交给JVM去处理,也许会是在循
环语句结束后,JVM才会去释放图片资源,其结果可能是你的程序还没有运行结束,操作系统已经宕掉。
5
但下面的好消息也许会让这个坏消息变得无关紧要。对于SWT,只需了解两条简单的“黄金”法则就可以
放心的使用系统资源!之所以称为黄金法则,一是因为少,只有两条,二是因为它们出奇的简单。第一
条是“谁占用,谁释放”,第二条是“父构件被销毁,子构件也同时被销毁”。第一条原则是一个无任何例外
的原则,只要程序调用了系统资源类的构造函数,程序就应该关心在某一时刻要释放这个系统资源。比
如调用了
Fontfont=newFont(display,"Courier",10,);
那么就应该在不在需要这个Font的时候调用
e();
对于第二个原则,是指如果程序调用某一构件的dispo()方法,那么所有这个构件的子构件也会被自动
调用dispo()方法而销毁。通常这里指的子构件与父构件的关系是在调用构件的构造函数时形成的。比
如,
Shellshell=newShell();
Compositeparent=newComposite(shell,);
Compositechild=newComposite(parent,);
其中parent的父构件是shell,而shell则是程序的主窗口,所以没有相应的父构件,同时parent又包括了
child子构件。如果调用e()方法,应用第二条法则,那么parent和child构件的dispo()方法也
会被SWTAPI自动调用,它们也随之销毁。
在任何操作平台的GUI系统中,对构件或一些图形API的访问操作都要被严格同步并串行化。例如,在
一个图形界面中的按键构件可被设成可用状态(enable)或禁用状态(disable),正常的处理方式是,用户对按
键状态设置操作都要被放入到GUI系统的事件处理队列中(这意味着访问操作被串行化),然后依次处理
(这意味着访问操作被同步)。想象当按键可用状态的设置函数还没有执行结束的时候,程序就希望再设
置该按键为禁用状态,势必会引起冲突。实际上,这种操作在任何GUI系统都会触发异常。
Java语言本身就提供了多线程机制,这种机制对GUI编程来说是不利的,它不能保证图形构件操作的同
步与串行化。SWT采用了一种简单而直接的方式去适应本地GUI系统对线程的要求:在SWT中,通常
存在一个被称为"用户线程"的唯一线程,只有在这个线程中才能调用对构件或某些图形API的访问操作。
如果在非用户线程中程序直接调用这些访问操作,那么SWTExcepiton异常会被抛出。但是SWT也在
6
*.y类中提供了两个方法可以间接的在非用户线程的进行图形构件的访问操作,这是通过的
syncExec(Runnable)和asyncExec(Runnable)这两个方法去实现的。例如:
//此时程序运行在一个非用户线程中,并且希望在构件panel上加入一个按键。
rent().asyncExec(newRunnable(){
publicvoidrun(){
Buttonbutt=newButton(panel,);
t("Push");
}
});
方法syncExec()和asyncExec()的区别在于前者要在指定的线程执行结束后才返回,而后者则无论指定的
线程是否执行都会立即返回到当前线程。
SWT的扩展:JFace
JFace与SWT的关系好比Microsoft的MFC与SDK的关系,JFace是基于SWT开发,其API比SWT更
加易于使用,但功能却没SWT来的直接。比如下面的代码应用JFace中的MessageDialog打开一个警告
对话框:
rning(parent,"Warning","Warningmessage");
如果只用SWT完成以上功能,语句不会少于30行!
JFace原本是为更加方便的使用SWT而编写的一组API,其主要目的是为了开发EclipIDE环境,而不
是为了应用到其它的独立应用程序。因此在Eclip2.1版本之前,很难将JFaceAPI完整的从Eclip的
内核API中剥离出来,总是要多多少少导入一些非JFace以外的Eclip核心代码类或接口才能得到一个
没有任何编译错误的JFace开发包。但目前Eclip组织似乎已经逐渐意识到了JFace在开发独立应用程
序起到的重要作用,在正在开发的2.1版本中,JFace也开始变成了和SWT一样的完整独立的开发包,
只是这个开发包还在变动中(笔者写本文时,应用的Eclip2.1M3版本)。JFace开发包的包前缀是以
开头。JAR包和源代码也和SWT一样,也在${你的eclip安装路径}plugins路径下去
找。
对开发人员来说,在开发一个图形构件的时候,比较好的方式是先到JFace包去找一找,看是不是有更简
洁的实现方法,如果没有再用SWT包去自己实现。比如JFace为对话框提供了很好的支持,除了各种类
型的对话框(比如上面用的MessageDialog,或是带有Title栏的对话框),如要实现一个自定义的对话框也
最好从JFace中的Dialog类继承,而不是从SWT中的*.继承。
7
应用JFace中的Preference包中的类很容易为自己的软件做出一个很专业的配置对话框。对于Tree、Table
等图形构件,它们在显示的同时也要和数据关联,例如Table中显示的数据,在JFace中的View包中为
此类构件提供了Model-View方式的编程方法,这种方法使显示与数据分开,更加利于开发与维护。JFace
中提供最多的功能就是对文本内容的处理。可以在.*包中找到数十个与文本处理相关
类。
与应用程序更近一步
Java程序通常是以class文件的方式发布的,运行class需要JRE或JDK的支持。这又是JavaGUI程序的
另一个致命的弱点,想象对一个面向广大用户的应用程序来说,无论你的程序功能有多简单,或是你的
代码十分的精简,你都不得不让用户去下载一个7、8M的JRE,那是多么令人沮丧的一件事。而且对程
序员来说,Class通常意味着源代码的暴露,反编译的工具让那些居心叵测的人轻易得到你的源代码。虽
然有很多对Class的加密方法,但那总是以牺牲性能为代价的。好在我们还有其它的方式可用:把Class
编译成exe文件!
下面介绍应用GCJ将SWT编译成exe文件的详细方法。作为对那篇文章的补充,就是目前也可以
通过下载Cygwin得到Windows下的GCJ。Excelsior也是笔者曾经用过的一款很好的编译器,唯一的遗
憾就是它的价格!
众所周知,Java语言在服务器上以及applet领域已经非常成功了,但是它在最终用户应用程序领域
为什么没有大行其道呢?有几个原因。首先,即使很小的应用程序的内存占用通常也有好几兆字节。第
二,与Java语言一起提供的GUI库产生的应用程序通常看起来与其本机同类应用程序不同。因此,无
论您的应用程序多么健壮或稳定,与本机应用程序相比,它都显得非常笨拙。
用于Java的GNU编译器
让我们从内存占用问题开始。Java应用程序要使用额外的内存,因为运行Java字节码时,虚拟机必须
完成许多“工作”。在当今高级编译器中,编译即时(just-in-time)发生并且编译器必须对这一信息立即
(on-the-fly)进行高速缓存以供以后使用。当然,现在内存是便宜,但是当有几个Java应用程序同时在
一台机器上运行时,即使是大机器也可能由于持续的内存页面调度而放慢速度。进入用于Java的GNU
编译器(GCJ)。GCJ获得Java源代码或字节码,然后将它们编译成本机机器代码。然后,可以将来自
几个Java类的机器代码链接在一起成为单个本机应用程序。
一月份,MartynHoneyford为我们提供了本机编译和GCJ的简介(请参阅参考资料以获取到Martyn文
章的链接)。正如他通过示例向我们展示的那样,本机编译的应用程序使用的内存通常要比在虚拟机中运
行的应用程序要少得多。
标准窗口构件工具箱
这很棒,但是正如Martyn指出的,GCJ尚不支持AWT或Swing。因此,我们现在将如何建立本机编
译的GUI应用程序呢?进入标准窗口构件工具箱(SWT)。这一API是开放源码Eclip工具平台的
一部分。为了避免引起Swing与SWT的对抗(请参阅参考资料以获取关于这场争论的更多详细信息),
让我说明一些SWT的优势。
8
SWT试图弥补AWT和Swing的缺点。使用AWT,我们将受到“最小公分母”限制:仅支持存在于所
有平台上的窗口构件。因为Motif没有提供本机树型窗口构件而Windows提供了该功能,AWT就没有
包含树型窗口构件。
Swing走向了另一个极端。虽然带有一个很出色的API进行优雅地设计,
Swing还是自己实现窗口构件。因此Swing不依赖于操作系统提供窗口
构件。无论本机是否支持,这都为Swing提供了不可思议的灵活性。但
是,因为Swing自己绘制这些窗口构件,所以最终的外观看起来与本机
应用程序有明显的不同。
SWT试图弥合这两个GUI工具箱之间的差距。它的行军命令是:“如果
有本机窗口构件就使用它。如果没有,就模拟它。”前面提到的树型窗口
构件就是这样一个示例。因为Windows支持本机树型窗口构件,所以在
Windows上运行时,SWT就使用它。但是,Motif不支持树型窗口构件,
因此SWT在Motif下运行时绘制其自己的窗口构件版本。使用SWT,
结果应用程序看起来与其本机的同类应用程序很相似,因为尽可能地使用
了本机窗口构件。
设置开发环境
因此,如何在本机编译所有这些应用程序呢?首先,您需要一个使用GCJ
设置的开发环境。目前,在Linux和其它UNIX变体(请参阅“Windows
上的GCJ”侧栏以了解GCJ在Windows上的情况)上支持GCJ。设置
开发环境的最简便方法是安装一种Linux分发版的新近版本。Mandrake
8.1和RedHat7.2都带有需另外安装的GCJ3.0.1。因为GCJ仍然在发展,所以可能想考虑使用最新
和最好的版本。我选择在版本3.0.3和3.0.4上进行测试。手工安装GCJ相对容易;GCJ页面提供了
相当好的文档(请参阅参考资料)。
一旦有了一个具有GCJ的环境,则下载EclipSDK并安装它。这将为您提供SWT源代码和字节码。
要安装EclipSDK,请下载ZIP文件(在EclipSDK标题下),然后将它解压缩到一个目录中。我
建议使用目录/usr/local/eclip,但是任何目录都可以。
开始编译
设置开发环境后,就可以开始编译了。编译应用程序包括对大多数SWT源代码执行与下面类似的命令:
-oMyClass.o
大约有30个SWT源文件使用Java本机接口(JavaNativeInterface(JNI)),因此我们需要以略微不同
的方式来编译它们(请注意-fjni标记):
-oMyJNIClass.o
Windows上的GCJ
Windows上的GCJ还未实
现。由于GCJ中存在一个涉
及与场合无关的文件系统(例
如,FAT和NTFS)的错误,
GCJ目前还不能在Windows
上运行。但是,在GCJ3.1中
接下来最好的一件事应该出
现。使用Linux,您将能把
GCJ设置成交叉编译器,它将
允许您在Linux上编译代码
而生成Windows二进制文
件。GCJ3.1是针对2002年
4月15日的发行版。请参阅
GCJ主页和邮件列表(在参考
资料中提及的)以获取最新的
发展。
9
最后,我们需要将结果对象编译成共享对象:
Class.o...
构建SWT
在本文中,我们将把SWT编译成共享对象,然后在产生的应用程序中动态引用这个对象。请注意,您
可以使用应用程序代码将SWT编译成可执行文件,但是基于本文所讨论的范围,我们将坚持编译成共
享对象。正如它的名称所表明的,共享对象的主要优点就是可以被共享。在运行时所有应用程序都可以
动态地使用同一个对象。产生的可执行文件大小将小得多。
使用下载源代码中包含的Ant构建文件(buildfile),我们将以自动方式编译SWT。这个文件完成两个
主要任务。首先,它将几个补丁程序应用到SWT源代码。(SWT文件中有三个将不能用GCJ进行编
译,这是因为一些小的编译器错误造成的—例如,它不喜欢intx,y,x1,y1作为一行;必须将它们分成
多行。在这些情况下,为这三个源文件编写了小的补丁程序以使它们在功能上等价。正如我以前提到的,
GCJ仍然在发展;这些错误会逐渐消除。)其次,构建文件使用提供的制作文件(makefile)来调用make。
在清单1中显示的Ant构建文件已经在Ant1.3和Ant1.4.1上测试过了。请注意,在清单中我除去了
注释以节省空间,但是有完整的代码可供下载。
要运行构建,请遵循下列步骤:
1.安装Ant(请参阅参考资料以获取关于Ant的更多信息)。
2.下载本文的源文件,它包含构建文件、补丁程序和关联的制作文件,然后将它解压缩到一个目录
中。
3.导航至SWT目录,然后输入ant。构建文件假设您已经在usr/local/eclip中安装了Eclip。
如果Eclip安装在另一个目录中,请输入ant-Declip_install_dir=your_directory,其中
your_directory是您安装Eclip的目录。
注:如果不想使用Ant构建文件,您可以手工解压缩SWT源文件和字节码,然后使用UNIXpatch命
令来应用源代码中包含的那三个补丁程序(使用.patch文件)。然后,运行制作文件。
清单构建文件
dest="${temp_dir}"/>
dest="${temp_dir}"/>
originalfile="${temp_dir}/org/eclip/swt/widgets/"/>
originalfile="${temp_dir}/org/eclip/swt/widgets/"/>
11
创建应用程序
既然您已经将SWT构建到共享对象中,您就可以尝试样本应用程序。显示在清单2中的应用程序由一
个显示经典“Hello,World!”消息的简单窗口组成。
清单2.“Hello,World”样本应用程序
y;
;
;
;
out;
publicclassHello{
publicstaticvoidmain(String[]args){
Displaydisplay=newDisplay();
finalShellshell=newShell(display);
RowLayoutlayout=newRowLayout();
y=true;
=true;
out(layout);
t("Hello,World!");
Labellabel=newLabel(shell,);
t("Hello,World!");
();
();
while(!od()){
if(!dDispatch())();
}
e()
要编译这个应用程序,请遵循下列步骤:
1.将SWT共享对象()复制到HelloWorld目录中,然后输入下列命令。(请记住,如果在
/usr/local/eclip以外的目录中安装了EclipSDK,请用您的目录来替换它。)
12
gcj-CLASSPATH=/usr/local/eclip/plugins//
--oHello.o
gcj-main=
2.接下来,使用下列命令设置库路径(假设您正在使用bashshell):
exportLD_LIBRARY_PATH=
.:/usr/local/eclip:/usr/local/eclip/plugins//ws/motif
3.输入./Hello,会看到本机编译的GUIJava应用程序出现屏幕上!
结束语
众所周知,Java语言具有一些重要的特性。它是优雅的,提供了面向对象概念的出色实现,并且具有一
个非常有用的标准类库。将这些优点与GCJ和SWT相结合使Java语言定位成在服务器和Web浏览
器上建立其基础,然后转向最终用户应用程序领域。
SWT内幕
要想弄清楚为什么一切都被弄得如此混乱,要从几年前只存在AWT的时候说起。SUN当时已经建
立了一套基本的可移植控件类,这些类映射到不同操作系统上的原生窗口组件(nativewidget),显然下
一步应该继续增强这套模型,除了初始的CUA92组件(文字、按钮等等),再继续加上表格、树、记事
本、滑块等等„„当时的AWT还满是漏洞,远不能称为可靠,还需要SUN的coder们去修补。SUN的
developer们如Graham和Otto总是习惯于公开把他们的bug归咎为操作系统的差异,比如“Windows和
OS/2的焦点次序不同”或者“在„„之间Ctrl-X的行为不一样”,以及其他苍白的托辞,好让批评的火
力从SUN太早释出代码这个问题的真相上移开。然后AmyFowler来到了SUN。不是我大男子主义,Amy
是个聪明的美女,大多数呆头呆脑只懂技术的开发人员都要被她捏在手里。
Amy来自一家Smalltalk公司,叫做Objectshare,在那里她负责搞UI类库。跟Java相比Smalltalk的历史
有些悲惨,曾几何时有3家庞大的Smalltalk公司——IBM、Parc-Place和Digitalk。在90年代初期3家公
司的市场份额大致相等,生活是美好的。Parc-Place采用仿窗口部件(emulatedwidgets)的设计(即Swing
的设计),IBM和Digitalk则采用原生窗口部件(nativewidgets)。后来IBM压倒了另外两家,因此他们
打算合并成一家,假设叫做Parc-PlaceDigitalk。随后当他们试图将他们的产品融合到一个叫做Jigsaw的
计划中时爆发了一场大战,计划由于政治原因失败了(开发人员实际上已经能让它运转起来),就因为原
生和仿造两派的死战。Amy赢得了精神上的胜利,不过在IBM我们赢得了他们所有的生意,因为这两家
13
公司在一整年里除了吵架什么都没做。当尘埃落定之后PPD(Parc-PlaceDigitalk当时已改名为Objectshare,
跟Windscale改名为Sellafield的原因相同——让人们淡忘之前发生的灾难)的股票价格从60美元掉到了
低于1美元1股。他们因为伪报收入被NASDAQ摘牌,从此消失。此时SUN正走上与PPD类似的技术
方向,于是PDD的技术人员都把他们的简历投到了SUN。Amy被雇佣了,她承诺通过轻量级方案解决
所有窗口组件的问题,因此说服SUN管理层让她当了GUI开发部门的头头。她是拿着“这里原来的人都
搞砸了,我是来解决的”的钥匙进来的。随后Amy雇佣了所有她过去在Parc-Place的旧朋友,让他们来
开发Swing。
显然Swing应该做的是仅仅成为一个绘制框架,给那些希望创建地图软件或者绘图软件的人们使用,无
论如何,应该围绕AWT类库来建造它,按钮之类的东西仍然交给AWT来管。SUN的人比如Philip和
Mark已经让AWT能够处理表格、树和记事本(notebook,?),所以Swing的方向应该说很明显了。但
那些毁了PDD的人不干,他们非要把一切都弄成轻量级的。由于SUN管理层的无知,再加上Amy无情
的政治手段,造成了我们今天所见的混乱局面。Amy还使SUN相信Swing是作为Mozilla项目的一部分
与Netscape联合开发的,事实上这只是她的宣传伎俩。
在IBM,我们从第一天起就憎恶Swing。庞大、满是错误,而且难看至极。原先我们的工具如
VisualAgeforJava都是用Smalltalk(用的是原生窗口组件)写的,所以当我们将这些工具向Java代码库
迁移时,我们需要一套窗口组件。IBM这边的开发人员都是原来搞Smalltalk的那一批人,我们对管理层
要求用Swing来构建WebSphereStudio工具都非常不情愿。Swing是个可怕的充满缺陷的怪兽。在
WebSphereStudio最初的预览中,当与MicrosoftVisualStudio作对比演示的时候,我们所有的客户都讨厌
它,就因为它的外观,而不管它的功能有多强。大多数消费者都不会买一辆让人觉得难看的车,哪怕这
车有一台出色的引擎。因此我们开始了一个项目,是把我们的Smalltalk原生窗口组件移植到Java上去。
这个项目是加拿大的ObjectTechnologyInternational小组做的。这个项目获得了成功,被运用在在我们发
布的VisualAgeMicroEdition产品中,VisualAgeMicroEdition后来成为J2ME开发方面一个非常成功的
IDE。但是OTI的人发现,Swing在读取Windows事件方面有极严重的缺陷,我们甚至无法进行SWT(S
开始是Simple的缩写,不过后来变成了Standard的缩写)和Swing间的互操作。他们在读事件队列的时
候用了一种可能留下内存漏洞的方式,所以我们不得不采用我们自己的查询Windows事件队列的循环,
以纠正这个错误。我们试了一次又一次让SUN修复这个错误,但Amy就是听不进去,所以我们才决定
SWT和AWT/Swing不能共存。我们甚至在SWT中定义了自己的Point和Rectangle类——整个工具包对
AWT或Swing都没有任何依赖。我们把这个工具包放到了Eclip中,这是一个工具平台,它的总体设
计目标就是要战胜Micrsoft和VisualStudio。Eclip是开源的,所以任何人都可以在上面构建自己的东西,
我们已经有像TogetherSoft和Rational这样的公司移植到了上面。我们的竞争者是Microsoft,所以我们所
有努力和注意力都是从正面针对Microsoft。
不管怎么说SUN对此非常不满。他们的Netbeans跟Eclip做的是相同的事,因此他们向IBM高层抱怨。
他们认为SWT是要将你绑到Windows上,这纯粹是胡说,因为SWT能通过GTK在Mac/Linux上运行,
以及一大堆嵌入式平台。他们拒绝让Eclip获得Java认证,因为里面有原生代码,所以Eclip产品必
须很小心地使用单词“Java”这个SUN的商标。Eclip甚至不能把自己称为一个JavaIDE,SUN已经威
胁过要采取法律行动来制止IBM在任何时候把Eclip称作一个JavaIDE。结果之一就是IBM在Eclip
上创建的GUI设计工具,允许你构建Swing/AWTGUI,却不让你往里面拖放SWT窗口控件。
将SWT从Eclip中分离出来是完全可能的,只需要把DLL抠出来放到路径中,并使用窗口组件工具包
14
来给你的银行或者保险或者其他什么应用程序开发GUI。再次说明,我们无法更进一步,因为SUN把我
们的双手绑上了。虽然作为Eclip开放源码协议的一部分,CPL允许我们提供这样的解决方案,但SUN
已经很清楚地表明他们不希望我们这样做。
对于用户社区来说,无论IBM和SUN的最终动机是什么,我发现有一点总是很有趣:喜爱Swing的人
总会说“一旦你花上几年时间去掌握它,你就能正确地使用它”,这基本上是他们在试图证明和维护他们
辛苦得来的用途有限的专门技术;而SWT的拥护者们说的是“哇,这真快,这跟原生的一样,还可以用
XP皮肤„„它还又轻又小”。有一句话是我喜欢的,我们的一个用户说,Swing就像Java决定不通过操
作系统来实现原生的IO,而是通过磁头马达API自己来读磁盘的扇区。Swing基本上就是这样的,它拿
着个底层的“paint(Graphics)”方法,自己来绘制所有的窗口组件。
后记:现在的情况已经有所不同,SWT到底还是单独发布了,VE也承诺在1.0版的时候支持SWT的GUI
设计。
本文发布于:2022-12-31 21:55:14,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/68061.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |