原文地址:http://blog.sina.com.cn/s/blog_661a8e550100ktt8.html
转载留用
Java世界中,目前最知名的三大GUI库分别是:
1、AWT(Abstract Window Toolkit)抽象窗口工具包库,包含于所有的Java SDK中
2、Swing高级图形库,包含于Java2 SDK中
3、来自IBM Eclipse开源项目的SWT(Standard Widget Toolkit)标准窗口部件库,不包含于JDK中,需要从Eclipse单独下载
一、AWT的原理:小巧却简单的GUI系统
AWT出现于Java 1.x中,是Java初期所内置的一种面向窗口应用的库。AWT使用的技术是对等设计模式(即Peer),其结构关系参见下图。
这就是Sun为什么要用Swing来诱惑我们离开AWT的主要原因。因为既然是对等模式,那么AWT就必须使用所有图形操作系统的图形接口功能的交集,因为 AWT的接口只有一套,所以,为了保证移植性,就只能使用所有系统都能够支持的最少特性。因而我们经常可以听见有人抱怨AWT的功能太少,图形太难看等等,这是为了保证移植性而作出的牺牲。
Swing的一些底层类是借用了AWT的Component、Container、Window等少数几个基础类。估计的原因是为了保持与AWT的兼容,方便大家将代码移植到Swing上。
下面是Swing的类关系图:
这种结构关系决定了Swing的庞大与复杂性。很多初学者都难以理解Swing的模式和结构。
Sun之所以用这种方式来实现,是为了在不牺牲移植性的基础上加入丰富的界面交互功能。
但是缺点也很明显:Swing的速度和效率是所有GUI系统中最慢的。
JBuilder和NetBeans的IDE都是纯正的Swing界面,启动一下,然后操作一下,比如拖动窗口之类的试试,你就会明白我在说什么。之所以导致这个结果,其原因是:
1、Swing的类层次太深,一个JFrame经过了4层的类继续关系,假如再加上虚拟机的图形功能内部实现,就有6层的转接关系,每一次的继续和转接都会消耗系统资源和速度损失。(过多的继续会降低系统的速度,因为操作子类往往是使用基类指向来完成通用操作的)
2、Swing是基于自绘制图形技术的,而Java为了保持可移植性,所以无法使用硬件加速和平台特性来加快图形操作的速度。因而Java的图形技术都是“高层”的图形技术,就似乎我们用Windows GDI去做动画一样,当然速度会很慢。
三、新的曙光-SWT
应该说,稍有阅历的Java的程序员都知道很多人对Swing效率低下的抱怨。IBM赞助的Eclipse开放源码项目,搞了一个另类的GUI系统-SWT。
SWT是一个非常独特的技术,其核心思想和Windows上的DirectX如出一辙,也许SWT的程序员真的是借鉴了DirectX成功的秘诀。
下面是SWT技术原理的类关系图:
我们会看见,SWT的类关系非常直接而且易懂,有点像Delphi的API接口思想(此是我随便乱弹,与Delphi没有什么关系)。最重要的一点就是SWT的核心思想:SWT的功能实现是完全构筑在以JNI为基础的,对运行平台的直接调用封装上的。
我们可以从图中看见,SWT的功能没有通过任何Java虚拟机来操作,而是直接调用Windows GDI和Shell功能,这一点是通过JNI方法调用完成。
一定会有人说SWT破坏了java的移植思想,不过Eclipse的大范围流行,正好证实了SWT非但没有阻碍移植性,反而提高了各种操作系统对于Java GUI的利用和期待。这不能不说Eclipse项目组是布满聪明的。
在Eclipse下,plugin目录的swt目录下,你可以发现一个dll动态库文件,这个dll就是JNI方法调用库。
基于SWT技术实现的Eclipse界面不但速度很快,效率很高,而且比Swing要美观的多。这就是直接调用封装的效果。
我们看看SWT的源代码就能更加明白为什么SWT那么流行,为什么SWT的速度像飞一样快,下面是从button类中抽取的一小段代码:
代码:
--------------------------------------------------------------------------------
int callWindowProc (int msg, int wParam, int lParam) {
if (handle == 0) return 0;
return OS.CallWindowProc (ButtonProc, handle, msg, wParam, lParam);
}
int windowProc () {
return ButtonProc;
}
LRESULT wmDrawChild (int wParam, int lParam) {
if ((style & SWT.ARROW) == 0) return super.wmDrawChild (wParam, lParam);
DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
int uState = OS.DFCS_SCROLLLEFT;
switch (style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) {
}
if (!getEnabled ()) uState |= OS.DFCS_INACTIVE;
if ((style & SWT.FLAT) == SWT.FLAT) uState |= OS.DFCS_FLAT;
if ((struct.itemState & OS.ODS_SELECTED) != 0) uState |= OS.DFCS_PUSHED;
RECT rect = new RECT ();
OS.SetRect (rect, struct.left, struct.top, struct.right, struct.bottom);
OS.DrawFrameControl (struct.hDC, rect, OS.DFC_SCROLL, uState);
return null;
}
我想任何一个有点Windows编程知识的人都会惊奇SWT的方式和做法,LRESULT、WindowProc都是做什么的,我想不用我多说了。我第一次看见SWT的代码时,惊奇的张大了嘴,我实在无法想象SWT项目组敢于将Java技术与Windows平台结合到如此紧密(当然,Linux平台版本也同样的结合紧密)。我居然在SWT里发现了一个叫Tray的类,猜猜看它是干什么的?Tray可以让你在java程序中显示一个任务栏图标,极度晕眩!
我想,不用再继续介绍SWT了,你一定也很兴奋,从SWT开始,JavaGUI并不一定意味着缓慢、低效率、弱小的功能,Windows程序的眩目与速度,Java程序也可以拥有,这就是SWT的价值。