历史 |
回到上个世纪90年代,曾几什么时候有3家庞大的Smalltalk公司——IBM、Parc-Place和 Digitalk。在90年代初期3家公司的市场份额大体相等,生活是美好的。Parc-Place采用仿窗口部件(emulated widgets)的设计(即Swing的设计),IBM和Digitalk则采用原生窗口部件(native widgets)。后来IBM压倒了另外两家,所以他们打算合并成一家,假设叫作Parc-Place Digitalk。随后当他们试图将他们的产品融合到一个叫作Jigsaw的计划中时爆发了一场大战,计划因为政治缘由失败了(开发人员实际上已经能让它运转起来),就由于原生和仿造两派的死战。
Amy赢得了精神上的胜利,不过IBM赢得了他们全部的生意,由于这两家公司在一全年里除了吵架什么都没作。当尘埃落定以后PPD(Parc-Place Digitalk当时已更名为Objectshare,跟Windscale更名为Sellafield的缘由相同——让人们淡忘以前发生的灾难)的股票价格从60美圆掉到了低于1美圆1股。他们由于伪报收入被NASDAQ摘牌,今后消失。git
当时,AWT已经出现了。SUN当时已经创建了一套基本的可移植控件类,这些类映射到不一样操做系统上的原生窗口组件(native widget),当时的AWT还尽是漏洞,远不能称为可靠,还须要SUN的coder们去修补。而后Amy被雇佣了,她承诺经过轻量级方案解决全部窗口组件的问题,以此说服SUN管理层让她当了GUI开发部门的头头。随后Amy雇佣了全部她过去在Parc-Place的旧朋友,让他们来开发Swing。
在IBM,VisualAge for Java最初是用Smalltalk(用的是原生窗口组件)写的,当将这些工具向Java代码库迁移时,他们须要一套窗口组件。IBM这边的开发人员都是原来搞Smalltalk的那一批人,他们对管理层要求用Swing来构建WebSphere Studio工具都很是不情愿。“Swing是个可怕的充满缺陷的怪兽“。所以开始了一个新的项目,把他们的Smalltalk原生窗口组件移植到Java上去。这个工具集后来被成为SWT,S开始是Simple的缩写,不事后来变成了Standard的缩写。这个项目得到了成功,被运用在发布的 VisualAge Micro Edition产品中。他们当时发如今Swing读事件队列的时候用了一种可能留下内存漏洞的方式,而不得不采用他们本身的查询 Windows事件队列的循环,以纠正这个错误。这促成了他们关于SWT和 AWT/Swing不能共存的决定。他们把这个工具包放到了Eclipse中,这是一个来自于早期Visual Age的工具平台。
你应该已经从上述的故事中对三者的历史有了大概的了解,尤为是SWT。如今你也许会以为,IBM建立SWT的理由是合理的而Swing应该沿用SWT采用的方式。这样的观点是片面的,当你深刻了解到Java的本质以后,你会发现其实并不像你想象的那么简单。数据库
先决条件
什么才是Java本质的,影响到工具集设计的特征呢?或者说,什么才是Java GUI工具集设计的先决条件呢?
编程
答案来自于Sun对Java的承诺之一:write once, run anywhere(一次编写,随处运行)。这是Java不一样于其余语言的优点所在。在Java被建立以前,软件的跨平台性能是开发者,特别是那些但愿对多平台提供支持的开发者的梦魇。在当今的生活中Internet的使用已经至关的广泛了,在世界不一样角落的人们在不一样的平台上工做着。软件提供商为不一样的操做系统提供支持是再平凡不过的事情。Java的write-once-run-anywhere(WORA)承诺显然减轻了开发者的负担,极大地提升了软件开发的生产力。
然而编写跨平台的应用程序,你必须使用支持平台无关性的标准库。这些标准库包括语言支持,公共用途,网络,I/O和GUI工具集等。因此当Sun开始设计GUI工具集的时候,首要任务就是考虑一个设计良好的平台无关的API。AWT和Swing都被当心地设计以保证平台兼容性。SWT则相反,它在设计之初并不以扩展性为原则,它为一个专有的IDE Visual Age for Java而设计,Windows做为这个IDE的首选运行环境拥有很高的优先级考量。SWT API相似于WIndows,一般它并不如Swing的扩展性好,尽管Steve Northover,SWT之父,辩称SWT是平台无关的,你能够很容易地发现许多Windows API的痕迹。
区别
GUI应用程序是软件的一种主要类型,因此Java的GUI库应该是标准化并被集成到JRE平台中的。然而不一样的操做系统有不一样的GUi风格和组件集。有一些组件在因此平台上有类似的观感。这些共有组件如按钮,标签,文本域,单选框等被称为标准组件。不一样的GUI工具集提供了不一样的组件集。GUI工具集老是遵循不一样的原则来选择组件类型和特征以实现。考察一个工具集,有两个不一样的要素:组件类型和组件特征。
Terms
首先让我图解两个数学概念:最大公约数和最小公倍数。以下图,三个集合表明不一样的操做系统。相交的部分是最大公约数,合并的部分是最小公倍数。设计模式
如今让咱们来考察Java GUI工具集AWT,SWT和Swing的组件类型和特征数组
AWT组件集遵循最大公约数原则,即AWT只拥有全部平台上都存在的组件的公有集合。因此你在AWT中没法获取如表或树等高级组件,由于它们在某些平台上不支持。AWT的组件特征一样遵循这一原则。它只提升平台上公有的特征。例如AWT按钮不能附着图片,由于在Motif平台上,按钮是不支持图片的。安全
因为它低劣的组件集和特征,AWT没法吸引开发者。它是Sun不推荐使用的,只是为了确保向下兼容和支持Swing。
SWT
SWT最初的目标之一是为了提供比AWT更为丰富的组件集。它遵循最小公倍数原则以提供一个各个平台上包含的组件的并集。思路是若是一个组件在某个平台上包含,那么SWT就会包装它并用java代码和JNI来调用它。若是一个组件在某一平台上不存在,它就会用继承并绘制Composite的方式来模拟组件。一个SWT Composite相似于AWT的Canvas。以这种方式,SWT提供了较AWT更为丰富的组件集。值得指出的是SWT的JNI封装不一样于AWT,它的模拟也不一样于Swing。
在组件特征方面,SWT相似于AWT。它遵循最小公倍数原则。在早期的SWT版本中,SWT按钮由于和AWT一样的缘由不支持附着图片。在以后的版本中,许多缺失的特征采用模拟的方式补全。但仍有许多特征没法采用纯粹的模拟实现。SWT将组件的控制交给本地操做系统。它难以扩展。只有例如图形装饰等特征能够借助模拟绘制来自定义实现。因此严格意义上将,SWT组件的组件集和特征因其难于扩展而不如Swing来得丰富。
Swing
Swing是三者中最强大和灵活的。在组件类型上,它遵循最大公约数原则。因为Swing能够控制自身GUI系统的所有并有很好的可扩展和灵活性,它几乎能够建立全部你想象获得的组件。惟一的限制是它的AWT容器。在Swing中你还不能跨平台地实现真正的透明化和不规则矩形窗口,由于Swing依赖于AWT顶层容器例如Applet, Window, Frame and Dialog等。除此以外,Swing几乎实现了全部平台上的标准组件。网络
在组件特征上,Swing遵循最小公倍数原则。它拥有全部平台上可提供的组件特征。不只如此,你还能够继承已有的Swing组件并添加新的特性。数据结构
上面比较主要是在API级别上的。让咱们将比较的焦点转移到实现细节上。Swing和SWT/AWT的区别是Swing是纯Java实现,而SWT和AWT是Java和JNI的混合。固然,它们的目标都是相同的,提供一个跨平台的APIs。然而为了达到这一点,SWT和AWT不得不牺牲一些组件和特性以提供一个通用的APIs。多线程
一个AWT组件一般是一个包含了对等体接口类型引用的组件类。这个引用指向本地对等体实现。举java.awt.Label为例,它的对等体接口是LabelPeer。LabelPeer是平台无关的。在不一样平台上,AWT提供不一样的对等体类来实现LabelPeer。在Windows上,对等体类是WlabelPeer,它调用JNI来实现label的功能。这些JNI方法用C或C++编写。它们关联一个本地的label,真正的行为都在这里发生。做为总体,AWT组件由AWT组件类和AWT对等体提供了一个全局公用的API给应用程序使用。一个组件类和它的对等体接口是平台无关的。底层的对等体类和JNI代码是平台相关的。
SWT
SWT也使用JNI的方法论来实现。但细节不一样于AWT。SWT的拥护者听到人们拿SWT和AWT相提并论但是会很生气的,Steve Northover,SWT之父,就曾为此抱怨过。
没错,它们是不一样的。让咱们深究SWT的代码。在SWT中,各个平台上惟一相同的部分是组件的接口,是类和方法的定义签名。全部的底层代码都是平台差别的。SWT为每一个平台提供了OS类。这个类用JNI封装了许多本地APIs。SWT组件类经过把这些JNI方法黏合在一块儿提供一个有意义的功能。
例如,在Windows上,文本域的选择是由一个系统调用处理的。这个系统调用在Windows的OS类中做为一个本地方法实现。因此在Windows平台的Text的setSelection方法中只用到了一个JNI调用。
然而,在motif上,文本域的选择包含两个本地调用。SWT就在motif的OS类中实现了两个调用。因此在motif上组件类须要做两次调用来实现文本的选择。
如今你应该能看出SWT和AWT的最大不一样了,它们使用了不一样的对等体编程方式来消除平台差别。SWT用java代码或有JNI实现的java对等体来黏合系统调用。而AWT把代码包含在对等体中,使状况复杂化了,我我的以为SWT的方法更加明智。
SWING
到了Swing这里,一切就变得清晰和直接了。除了顶层容器,Swing的实现不依赖于具体平台。它掌管了全部的控制和资源。Swing所须要的是事件输入来驱动系统,以及承接自顶层AWT容器的图形处理,字体和颜色。普通的Swing组件能够看做是AWT容器的一块逻辑区域。它们并无注册对等体。全部添加到同一顶层容器的Swing组件共享它的AWT对等体以获取系统资源,如字体,图形处理等。Swing将组件本身的数据结构存储在JVM的空间中。它彻底由本身管理画图处理,事件分发和组件布局。
因为AWT和SWT都持有对本地组件的引用,它们必须以正确的方式释放这些引用以免内存泄露和JVM崩溃。AWT将绝大多数资源管理任务交给系统,将开发者从单调乏味的资源管理中解救出来。然而这使得AWT的实现复杂化了。一旦它实现了,开发者不多有机会犯错误并使他们的程序崩溃。
SWT用的是另外一种方法。大致上,SWT让开发者本身来管理资源。它的一条著名的规则是:谁建立,谁释放。所以开发者必须谨慎地显式调用dispose方法释放每个由他建立的组件和资源。这简化了SWT的实现模型,但把开发者摆在了因错误编码而易于形成程序崩溃这一风险之上。
模拟方式的区别
Swing和SWT在它们的实现上都使用了模拟。SWT只模拟平台上缺失的组件。区别是SWT的模拟更像是AWT的Canvas实现的模拟。SWT的Composite类有它本身在操做系统中相应的对等体。它从本身的对等体中得到全部它所须要的资源如图形处理的对象,字体和颜色等。它直接从操做系统获取全部的事件并进行处理。然而,Swing组件在操做系统中没有相应的对等体。它只是一块顶层容器中的逻辑区域,实际上它从顶层容器的对等体中借用资源。Swing的事件并非底层系统产生的事件。它们实际是由顶层容器处理AWT事件所产生的伪事件。咱们会在稍后的事件部分中详细介绍它。
另外一个不一样之处是Swing组件的z-order系统是来自于AWT组件的。如上所述,Swing组件与顶层AWT容器共享一个对等体。所以,Swing组件也和顶层容器有相同的z-order。SWT和AWT组件都有不一样于顶层容器的z-order,一般是高于顶层容器。故而若是AWT组件和Swing组件混合在一块儿的话,Swing组件将可能被AWT组件遮住。当操做系统开始更新UI的时候,顶层容器和Swing组件老是先于AWT组件绘制。当它们完成绘制,AWT组件会覆盖Swing可能绘制过的地方。所以不提倡Swing和AWT组件的混用。若是有一个浮动的Swing组件如菜单,AWT组件极可能遮盖菜单。
布局管理器
并非三者中的全部部分都是不一样的。布局管理器是一个例外。开发GUI应用程序,当容器改变大小的时候,组件须要重定位或改变大小。在传统的编程语言中,这依靠监听大小改变的事件来实现。相应的片断散落在源代码的各个角落下降了程序的可读性。Java引入了将布局代码封装的思路,称之为布局管理器。当布局管理器对象被设置到一个容器中,它自动处理大小改变的事件。当大小改变时,管理器的布局方法被调用以重定位子组件或调整它们的形状。
AWT,SWT和Swing都以这样的方式来组织,而都有它们各类独特的布局管理器。因为AWT和Swing拥有一个共同的超类java.awt.Component,它们的布局管理器能够交替地使用。
Look And Feel观感
包括SWT和AWT在内的本地工具集并不支持Look And Feel机制。它们将组件捆绑在操做系统上,有其优点和劣势。其中的一个劣势是它们不支持可插拔的Look And Feel。将绘制处理交由操做系统完成剥夺了它们实现自定义组件Look And Feel的能力,也就使得它们没法提供这种机制。Look And Feel机制愈来愈成为GUI工具集中不可缺乏的一部分。
Swing拥有很好的Look And Feel支持。你甚至能够动态地改变Swing应用程序的Look And Feel,鉴于AWT和SWT将组件控制彻底交给操做系统处理,这是它们所没法超越的任务。我曾经听不少人抱怨过Sun在Swing上的设计。他们以为Swing为何不像SWT那样沿用AWT的思路呢?事实上,Look And Feel机制正是Swing走到这个方向上的缘由之一。若是Swing遵循的是包装已有的组件并模拟不存在的组件的路线,那它就没法提供Look And Feel机制。由于提供Look And Feel机制是本地策略所没法完成的任务。
Swing做为一个仿生系统,它的图形工具集较之AWT和SWT强大许多。Swing基于其自身系统中的两个基础组件群:Java 2D和AWT。Java 2D在Java中是强大的类库,它为高级图像处理,颜色管理,图形绘制和填充,坐标系变换和字体生成提供丰富的特性。相较之下,AWT和AWT仅对这些特性提供有限访问,它们是相对原始和低级的。
Swing和AWT在设计之初就秉承了JavaBeans规范,它们的组件类与JavaBeans规范一致。然而SWT并无很好的遵循这一规范。例如,在SWT的组件类中没有无参的构造器。每一个组件都必须至少拥有一个单参数的构造器。这个参数就是父组件的引用。这意味着不管什么时候组件被建立,它都直接被添加到一棵组件树中。一个组件没法脱离于已注册的本地对等体而存在。这样,SWT就能让由编程者建立的组件在display的dispose方法被调用的时候自动被释放。
SWT的组件构造器策略能够排除某些内存泄露的可能性。AWT在资源管理方面也有相似的问题。但它采用了不一样的方式解决。当AWT组件被建立的时候,相应的对等体并不会当即被建立。即使它被添加到一棵组件树,而若是这棵树还不可见,那么对等体仍不会被建立。只有当顶层容器被设为可见,这些对等体才会被建立。建立对等体的方法一般在addNotify中,它们一般递归地调用父组件的addNotify直到整棵组件树上的对等体都被建立了。当顶层容器由dispose方法销毁的时候,一个对应的方法removeNotify将会被递归地调用以释放这些对等体。这样,AWT在不禁开发者介入的状况下管理了它的资源。
一个事件要求特定的动做被执行,它被做为消息由外界或系统自身发送给GUI系统。这些事件包括来自计算机设备如鼠标键盘和网络端口的I/O中断,以及GUI系统的逻辑事件触发,好比一个按钮的ActionEvent事件。
事件分发遵循两种不一样的模型。单线程分发模型和多线程分发模型。
在单线程分发模型中,一个事件从队列中抽出并在同一个线程中被当即处理。事件处理后,紧跟着的下一个事件再被抽出并继续下一轮的循环。在多线程分发模型中,从队列中获取事件的线程启动另外一个被称做任务线程的线程,并把事件交给它处理。而获取事件的线程并不等待处理线程的结束。它简单的获取下一个线程并分发它。
事件处理一般涉及应用程序的数据变化。并且这些数据常常是组件须要显示的。多线程分发很容易产生同步问题,它产生多个可能互相干扰的事件处理线程。在一个稳定的GUI系统中,组件应该可以保持视图与模型间的同步。因为同步问题的出现,多线程模型要求开发者拥有更多并发编程的经验。而对于普通编程人员,形成同步错误是很容易的。所以许多GUI系统并不使用这一模型。
单线程模型经过强制事件序列化地被处理提供了实际上的同步。AWT,SWT和Swing 都采用了这一模型来分发事件。但单线程模型也会有它本身的问题。其中之一就是线程专一。既然全部的事件都在一个线程中被分发,若是其中的一个事件的处理费时太久,将会拖延下一个事件的抽取和执行。若是有一个PAINT事件被延后,那么在屏幕上就会呈现为没法响应。这常用户感受到软件很慢。许多这样的低效程序是因为开发者的经验不足形成的。他们的作法是将耗时任务填充到监听器方法中。因为这种错误的编程方式在Swing中大量被使用而尤其突出,这也是它慢而丑陋的坏名声的由来之一。实际上,若是你懂得使用线程,Swing应用程序能够表现出很高的响应度。
Thread Safety线程安全
上述问题的解决方案是启动一个单独的工做者线程来完成耗时处理,这样就能把事件分发线程释放处理以继续运做。如多线程模型中所作的那样,然而这一样会引入在多线程模型中出现的同步问题。许多GUI工具集都有本身先天性的机制来解决这一问题,例如,在组件树上的组合锁。开发者不须要为如何安全编程而操心。这样的工具集被成为线程安全的。AWT就是其中之一。
然而,因为没必要要的同步使得创建这样的GUI系统过于负责并形成了额外的开销。所以,Swing和SWT被设计为非线程安全的,这意味着开发者必须谨慎地实现他们的多线程任务。SWT和Swing在运行时线程安全行为上有一个小小的区别。SWT老是检查改变组件的操做是否在事件分发线程上执行。这样,开发者就可以发现同步问题。而Swing不这样,这是Swing的一个不知之初,这其实并不难实现。
Event Dispatching Thread事件分发线程
AWT读取操做系统中的基本事件并在java代码中处理它们。AWT事件分发线程被命名为?AWT-{OS}-Thread。这个线程由AWT系统隐式启动。当AWT应用程序启动时,这个线程在背后启动,在操做系统上抽取和移除事件。当诸如按钮动做这样的逻辑事件被触发时,它传递给注册在按钮上的操做监听器。开发者也能为AWT组件编写鼠标,键盘和绘制事件的事件监听器。这一般经过扩展AWT Canvas组件来完成。这一组件支持了全部已提供的事件,并且你能够经过重写事件处理方法,实现一个自定义的组件。
然而,在Swing中,这是一个不一样的线程。Swing把AWT事件做为自身事件系统的一个输入。它获取AWT事件并作一些初始化处理,产生一个对应的Swing事件并把它放到本身的事件队列上。Swing也有本身的事件分发线程,一般命名为EventQueue-0。这个线程从事件队列中抽取Swing事件,就如同AWT从操做系统中抽取那样。而后它把事件分发给目标组件。一般事件首先被分发给组件的顶层容器,而后由顶层容器的dispatch方法处理,它可能被再分发或重定向到一个Swing组件,在那里继续由本身的监听器进行处理。
例如,当一个鼠标移过一个JButton或JFrame时,一个指向JFrame的AWT事件在AWT线程上触发。AWT线程检查它是否须要做更多的处理,而后把它包装成一个Swing的MouseEvent对象并把它添加到EventQueue队列中。当得到MouseEvent事件后,EventQueue-0抽取这个事件并判断出目标Swing组件。这里,这个组件是JButton。而后它产生了一个包含相对坐标位置和事件源的新的MouseEvent重定向到这个JButton上,而后调用这个JButton的dispatch以继续分发。JButton的dispatch过滤事件给特定的方法最终实现由鼠标监听器在该点上的分发的点击。
SWT更相似于AWT。惟一的区别是它要求开发者显式地书写事件循环代码。然而底层的实现细节是不一样于AWT的。看看SWT的读取和分发事件代码,它会让你想起MFC的代码风格。
AWT,SWT和Swing都有类似的事件监听器模型。它们都使用观察者模式,组件和监听器的链接方式是把监听器添加到组件上,这组成了一个对象网络的模型。当事件被触发并分发给组件,组件调用它的监听器以处理事件。一个监听器也能够继续分发事件给后续的处理,或产生一个新的事件并把它广播到网络中的其余节点上。基本上有两种不一样的广播事件方式。一种是同步调用监听器。另外一种是异步地将事件发送回队列,它将在新一轮的事件分发中被分发出去。
除了直接发送给队列的方式,Swing还有一些其余的分发异步事件的方法。其中之一是调用SwingUtilities 或EventQueue 的invokeLater,这一方法包装一个Runnable对象到事件中并把它发送给事件队列。这确保了Runnable的run方法能在事件分发线程上执行,保证了线程安全。实际上,Swing的Timer好SwingWorker基于这一机制实现。SWT也有相应的发送异步事件的方式。它的invokeLater的对应方法是display.asyncExec,它以一个Runnable对象做为参数。
我从一个技术层面给出了他们优劣势上的一个清单,以结束本文。
AWT是Sun不推荐使用的工具集。然而它在许多非桌面环境如移动或嵌入式设备中有着本身的优点。
更少的内存。它对运行在有限环境中的GUI程序的开发,是合适的。
1.更少的启动事件。因为AWT组件是本地由操做系统实现的。绝大多数的二进制代码已经在如系统启动的时候被预装载了,这下降了它的启动事件。
2.更好的响应。因为本地组件由操做系统渲染。
3.从java 1.x时代就为JRE支持的标准GUI工具集,你不用单独安装它,你不用担忧平台差别的问题。
4.成熟稳定的。它可以正常工做并不多使你的程序崩溃。
然而,事物都有它们很差的一面。让咱们来例数它吧。
1. 更少的组件类型。表和树这些重要的组件缺失了。它们是桌面应用程序中广泛使用的。
2.缺少丰富的组件特征。按钮不支持图片附着。这很明显是它遵循的设计原则形成的。
3.不支持Look And Feel。AWT被设计为使用本地组件。所以,它依赖系统来提供Look And Feel支持。若是目标系统并不支持这一特性,那么AWT将没法改变它的Look And Feel。
4.无扩展性。AWT的组件是本地组件。JVM中的AWT类实例实际只是包含本地组件的引用。惟一的扩展点是AWT的Canvas组件,你能够从零开始建立自定义组件。然而没法继承和重用一个已有的AWT组件。
SWT
SWT有以下优点:
1.丰富的组件类型。SWT提供了种类繁多的组件,从基础组件如按钮和标签到高级的表格和树。
2.相对的丰富组件特性。尽管SWT也遵循最大公倍数原则,它采用模拟的方式从新设计了对更多组件特性的支持。因此同AWT相比,它有着相对丰富的组件特性。
3.更快的响应时间。基于和AWT一样的缘由,SWT组件包装了本地组件,由操做系统实现渲染。操做系统一般对渲染处理作了优化,保存GUI二进制代码为标准库,减小了内存的使用,提升了响应性能。
4.更少的内存消耗。既然操做系统为本地组件提供了优化,这一点就容易理解了。
不足之处:
1.不在JRE的标准库中。所以你必须将它和你的程序捆绑在一块儿,并为你所要支持的每一个操做系统建立单独的安装程序。
2.不够成熟和稳定。SWT因其设计上的一些缺陷,如资源管理,Windows友好等,被认为是不稳定的。它能够在Windows上表现得很好,但在其余操做系统上,它常常是不稳定且容易崩溃的。这很大程度上是由于它把资源管理交给开发者来处理,而并非全部的开发人员可以正确地处理这些。
3.在非Windows平台下的性能不高。如同第2点提到的,SWT被设计为与Windows API相协调的,这致使了在非Windows平台上的性能问题,糟糕的UI感官,不稳定甚至内存泄露。
4.无Look And Feel 支持。和AWT一样的缘由。
5.不可扩展,和AWT一样的缘由。在SWT中你能够经过有限的方式扩展一个组件,例如,监听PAINT事件并添加自定义绘图到组件上,但鉴于你只能控制绘制处理的一部分,这是十分有限的。你也只能在操做系统绘制完组件后补充,这并不能很好支持自定义。许多应用程序在自定义行为上有很高的要求。
SWING
Swing是三者中最强大的GUI工具集。它和另外二者相比一样有本身的优劣势。
一、丰富的组件类型。Swing提供了很是普遍的标准组件。这些组件和SWT同样丰富。基于它良好的可扩展性,除了标准组件,Swing还提供了大量的第三方组件。许多商业或开源的Swing组件库在开发多年后都已经能够方便地获取了。
二、丰富的组件特性。Swing不只包含了全部平台上的特性,它还支持根据程序所运行的平台来添加额外特性。Swing组件特性遵循特定原则,易于扩展,所以可以提供较SWT和AWT更多的功能。
三、好的组件API模型支持。Swing遵循MVC模式,这是一种很是成功的设计模式。它的API成熟并设计良好。通过多年的演化,Swing组件APIs变得愈来愈强大,灵活和可扩展。它的API设计被认为是最成功的GUI API之一。较之SWT和AWT更面向对象,也更灵活而可扩展。
四、出色的Look And Feel支持。MVC设计模型容许Swing分离组件视图和它的数据模型。它有高级的UI委托来将UI渲染委托给UI类。这些类被注册到一个展示特定的Look And Feel的对象上。已经有上百个Look And Feel 能够提升各类各样的GUI风格。你甚至能够基于其余人的成果编写组件的Look And Feel 。
五、标准的GUI库。Swing和AWT同样是JRE中的标准库。所以,你不用单独地将它们随你的应用程序一块儿分发。它们是平台无关的,因此你不用担忧平台兼容性。
六、成熟稳定。Swing已经开发出来7年之久了。在Java5以后它变得愈来愈成熟稳定。因为它是纯Java实现的,不会有SWT的兼容性问题。Swing在每一个平台上都有相同的性能,不会有明显的性能差别。
七、可扩展和灵活性。Swing彻底在Java空间中实现。它能够控制它所须要的一块儿。Swing基于MVC的结构使得它能够发挥Java做为一门面向对象语言的优点。它提供了许多扩展组件的方法。让咱们来列举一下:
A.继承已有组件;
B.靠复合组件的方式扩展。
C.从零开始使用JComponent编写自定义组件;
D.使用渲染器和编辑器机制扩展复制的Swing组件,如JList,JComboBox,JTable,JTree等;
E.基于已有Look And Feel 或从零开始建立新的Look And Feel;
F.使用LayeredPane,GlassPane或拖放机制开发高级的组件,例如浮动的固定组件,自定义弹出窗口,自定义菜单等。
八、整体上良好的性能。Swing的速度是其为人诟病的一点。然而随着JRE的开发,Swing的性能现在已经有了很大的提升。特别是Java5以后,Swing的整体速度可以接近本地小控件系统。
一个GUI的速度老是从两个方面被衡量:响应时间和数据反馈时间。
响应事件指从事件任务出现到组件更新UI的这段时间。例如按下一个按钮,拖动一个组件,改变一个多标签面板等。在这个方面本地组件总能比模拟组件有更好的响应。AWT和SWT一般比Swing表现出更好的响应时间。然而事实并不是老是如此。这取决于操做系统。若是本地组件没有被良好的实现,那结果就是相反的。例如Windows开发了不错的GUI库,而Linux平台一般差得较远。SWT可能在Windows上表现得比Swing好,而在Linux上表现得比Swing差。也就是说,AWT/SWT的性能决定于底层平台。随着JRE的开发,Swing的响应性能可以随着JVM的优化,更好的实现方式,以及图形硬件加速而获得长足的改进。在Windows上,Java6的Swing能够媲美SWT的性能。在非Windows环境中,Swing能够表现出更好的响应时间。
数据输送时间是指用于将应用程序数据传递给UI组件所须要的时间。例如,一个学生管理系统要求从数据库中装载学生信息并在一个表格中显示出来。花费在从内存到表格组件的数据传递时间被称为数据输送时间.在这个方面,Swing一般比其余两者的性能更好。或许当数据量不大的状况下并不明显。但当海量的数据被输送给表格的时候,这一点就显而易见了。为了理解这一点,提醒你注意JVM和本地操做系统是两个分离的运行时环境。因为JNI的调用在两个环境中跨越式地发生,一般比一个普通的Java调用花费更长的时间。一般这包含两个处理。一个是Java数据结构转换为本地数据结构,另外一个是方法返回时的本地数据结构转换为Java对象。其余的性能开销暂时忽略不计。当一个大范围数组的数据从本地组件中输送过来,大量反复的JNI调用将极大地拖垮性能。
Swing的另外一个优点是它有许多的组件模型以提升输送的性能。例如TableModel被映射为两个维度上的数组。这样,在Swing组件中甚至不须要进行数据方式的转换。Swing直接将应用程序数据显示在屏幕上,节省了在数据转换上所花费的事件。
Swing也有不足之处:
比AWT和SWT更多的内存消耗。Swing本身实现了全部组件。所以,它在运行时装载了大量的类。一些其余的问题来源于小的可变对象的建立,如Rectangle,Point,这些对象基于同步的考虑一般不可重用。Java在堆上建立因此对象。小的对象一般致使了额外的堆空间消耗。许多小的对象较之大对象更难以有效地被垃圾回收。所以,Swing应用程序一般没法及时回收大而小的对象。这种状况的广泛就会致使性能降低。
更多的启动时间。如今JVM已经快得多了。许多人甚至扬言它能够媲美C++的实现。但多数的Java应用程序仍是看上去很慢。实际上,Java性能的不少问题来源于类装载机制。这是一个I/O操做,故而可以明显地下降Java应用程序的速度。也许这是每一个动态连接系统中都要面对的问题吧。Swing一般包含了上千个Swing类的使用,在Swing应用程序能够显示它的主窗口以前,它比AWT或SWT装载了多得多的类。这严重下降了Swing的启动时间。这种问题也许会相对好一点若是Swing的类是以共享系统库的方式预加载的。
上述的比较总的来讲是技术上的总结。相对其余方面的因素也会影响你对一个工具集的选择。例如,文档,支持,学习曲线和社区等,但既然咱们关注的是技术层面,就不在这里讲的太多了。