Java中AWT、Swing與SWT三大GUI技術的原理與效率差異


Java中AWT、Swing與SWT三大GUI技術的原理與效率差異

看了一下對Java GUI討論的帖子,所以寫了一篇文章來闡述一下各種GUI技術的優劣。
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),其結構關系參見下圖。


從這幅類關系圖很容易看出AWT的技術實現和Peer設計模式。圖中,黃色的類是java.awt包中的類,淺灰色部分是Java虛擬機部分,而深灰色則是Windows平台。
awt的重點是對等Peer設計模式。所謂Peer對等設計模式就是將awt控件直接對應到運行平台上的一個類似或者等同控件上。比如圖中的Button類就是對應了深灰色的Windows的標准Button功能。
對等模式用於在兩個控件間之間建立一個相互作用的聯系,而充當紐帶的則是Java虛擬機和虛擬機-GDI的接口(以Windows為例子)。所以,我們可以看出,awt首先需要經過通用的Java技術來控制圖形、事件等,然后Java虛擬機再將請求傳送到具體的平台圖形和控件接口去交互。
對等模式的效率並不很高,因為AWT通過了虛擬機和虛擬機-GDI這兩個層次來完成一個操作,經過的層次系統越多,速度和效率就越慢。而且Peer對等模式有一個致命的弱點:移植性非常差!
這就是Sun為什么要用Swing來誘惑我們離開AWT的主要原因。因為既然是對等模式,那么AWT就必須使用所有圖形操作系統的圖形接口功能的交集,因為 AWT的接口只有一套,所以,為了保證移植性,就只能使用所有系統都能夠支持的最少特性。因而我們經常可以聽見有人抱怨AWT的功能太少,圖形太難看等等,這是為了保證移植性而作出的犧牲。

二、猛獁巨獸的誕生-Swing

從Java2 即Java 1.2版本開始,Sun開始在JDK中提供一套新的圖形界面接口系統-Swing。所有Java愛好者都投入了對Swing的研究和迷戀。隨着一大批使用Swing作為界面技術的IDE和程序出現,很快大家都意識到Swing的問題所在。
一些人認為Swing是輕量級的GUI系統,無論官方如何說,沒有一個Java程序員會認為Swing是輕量級的,相反,Swing是一個非常巨大的GUI庫,這一點已經是Java界的共識。
Swing的一些底層類是借用了AWT的Component、Container、Window等少數幾個基礎類。估計的原因是為了保持與AWT的兼容,方便大家將代碼移植到Swing上。
下面是Swing的類關系圖:


菊黃色類為Swing包的類。對比一下Swing的圖與AWT的圖,我們可以發現,Swing圖中,awt體系中的深灰色Windows控件類已經被去掉了。因為Swing不再沿用Peer對等模式來實現GUI界面。
這是Swing的核心思想之一,Swing是完全基於Java自繪制圖形而實現的,因而Swing的界面看起來與Windows不再有任何類似,尤其是窗口控件的樣式(雖然我們也可以通過換膚來達到模擬Windows界面的效果)。
所以上圖清楚的表明了Swing是一個高層的GUI系統,而不像AWT那樣與運行平台技術更加靠近的系統。我們仍然用Button與Panel來做了一個例子,圖中關系看出,Swing的類繼承關系比AWT要復雜的多,而且Swing類大多都經過了中間的轉接類-JComponent。而我們常用的JFrame則另辟蹊徑,從awt的window繼承了下來。
這種結構關系決定了Swing的龐大與復雜性。很多初學者都難以理解Swing的模式和結構。
Swing 中的控件都是利用Java圖形功能繪制出來的,而不是對應到平台的一個具體控件實現。我們所用的所有Swing控件都是直接或者間接用Graphics繪制出來的,這種實現方式最大的好處是很靈活,我們想要什么樣的控件,就直接用Graphics繪制出來就是了。
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)) { 

   case SWT.UP: uState = OS.DFCS_SCROLLUP; break;

   case SWT.DOWN: uState = OS.DFCS_SCROLLDOWN; break;

   case SWT.LEFT: uState = OS.DFCS_SCROLLLEFT; break;

   case SWT.RIGHT: uState = OS.DFCS_SCROLLRIGHT; break;

 }

 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的價值。
更加重要的是,SWT打破了長久以來人們對於移植性的誤區,似乎移植性就只能使用少到可憐的功能,我們也可以用JNI來擁抱Java的世界,我想,將來不僅僅是界面會借助JNI的方式,也許我們的很多Java思想都會悄悄的發生改變,也許有一天我們的Java代碼可以運行的像VB一樣快,這種思想意識的變革就是SWT的價值。

至於Swing的結局,我不知道,但是我知道我更加喜歡輕量級的而且快速的SWT,給你的程序多一個選擇吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM