1. 程式人生 > >GUI開發之AWT、SWING、SWT和JFACE的比較

GUI開發之AWT、SWING、SWT和JFACE的比較



AWT

Abstract Windows Toolkit(AWT)是最原始的 Java GUI 工具包。在任何一個 Java 執行環境中都可以使用它。

AWT 是一個非常簡單的具有有限 GUI 元件、佈局管理器和事件的工具包.有些經常使用的元件,例如表、樹、進度條等,都不支援。

通常對於 AWT 來說(也適用於 Swing 和 SWT),每個事件型別都有一個相關的 XxxListener 介面(XxxAdapter 的實現可能為空),其中 Xxx 是去掉 Event 字尾的事件名(例如,KeyEvent 事件的介面是 KeyListener),用來把事件傳遞給處理程式。應用程式會為自己感興趣處理的事件的事件源(GUI 元件或部件)進行註冊。有時監聽介面要處理多個事件。

AWT 的一個很好的特性是它通常可以對 GUI 元件自動進行銷燬。這意味著您幾乎不需要對元件進行銷燬。一個例外是高階元件,例如對話方塊和框架。如果您建立了耗費大量主機資源的資源,就需要手動對其進行銷燬。

AWT 元件是 “執行緒安全的(thread-safe)”,這意味著我們不需要關心在應用程式中是哪一個執行緒對 GUI 進行了更新。這個特性可以減少很多 GUI 更新的問題,不過使 AWT GUI 執行的速度更慢了。

AWT 讓我們可以以自頂向下(top-down) 或自底向上(bottom-up) 或以任意組合順序來構建 GUI。自頂向下的意思是在建立子元件之前首先建立容器元件;自底向上的意思是在建立容器(或父)元件之前建立子元件。在後一種情況中,元件的存在並不依賴於父容器,其父容器可以隨時改變。

由於 AWT 要依賴於主機 GUI 的對等體(peer)控制元件(其中每個 AWT 元件都有一個並行的主機控制元件或者對等體)來實現這個 GUI,這個 GUI 的外觀和行為(這一點更重要)在不同的主機上會有所不同。這會導致出現 “編寫一次隨處測試(write once, test everywhere,即 WOTE)” 的情況,這樣就遠遠不能滿足我們的要求了。

AWT 提供了一個豐富的圖形環境,尤其是在 Java V1.2 及其以後版本中更是如此。通過 Graphics2D 物件和 Java2D、Java3D 服務,我們可以建立很多功能強大的圖形應用程式,例如畫圖和製表包;結合使用 JavaSound,我們還可以建立非常有競爭力的互動式遊戲。

Swing

Java Swing 是 Java Foundation Classes(JFC)的一部分,它是試圖解決 AWT 缺點的一個嘗試。在 Swing 中,Sun 開發了一個經過仔細設計的、靈活而強大的 GUI 工具包。

Swing 是在 AWT 元件基礎上構建的。

為了克服在不同主機上行為也會不同的缺點,Swing 將對主機控制元件的依賴性降至了最低。實際上,Swing 只為諸如視窗和框架之類的頂層 元件使用對等體。大部分元件(JComponent 及其子類)都是使用純 Java 程式碼來模擬的。這意味著 Swing 天生就可以在所有主機之間很好地進行移植。因此,Swing 通常看起來並不像是本地程式。實際上,它有很多外觀,有些模擬(儘管通常並不精確)不同主機的外觀,有些則提供了獨特的外觀。

Swing 對基於對等體的元件使用的術語是重量級(heavyweight),對於模擬的元件使用的術語是輕量級(lightweight)。實際上,Swing 可以支援在一個 GUI 中混合使用重量級元件和輕量級元件,例如在一個 JContainer 中混合使用 AWT 和 Swing 控制元件,但是如果元件產生了重疊,就必須注意繪製這些控制元件的順序。

Swing 無法充分利用硬體 GUI 加速器和專用主機 GUI 操作的優點。結果是 Swing 應用程式可能比本地 GUI 的程式執行速度都慢。Sun 花費了大量的精力來改進最近版本的 Swing (Java V1.4 和 1.5)的效能,這種缺點正在變得日益微弱。由於 Swing 的設計更加健壯,因此其程式碼基礎也更堅實。這意味著它可以在一臺健壯的機器上比 AWT 和 SWT 上執行得更好。

與 AWT 一樣,Swing 可以支援 GUI 元件的自動銷燬。Swing 還可以支援 AWT 的自底向上和自頂向下的構建方法。

與 AWT 不同,Swing 元件不是執行緒安全的,這意味著您需要關心在應用程式中是哪個執行緒在更新 GUI。如果在使用執行緒時出現了錯誤,就可能會出現不可預測的行為,包括使用者介面故障。有一些工具可以幫助管理執行緒的問題。

與 AWT 類似,Swing 的一個優點是,它也是 Java 技術的一種標準配置。這意味著您不需要自己來安裝它了。不幸的是,Swing 已經有了很大的變化,因此它很容易變得依賴於最新版本的 Java 語言所提供的特性,這可能會強制使用者更新自己的 Java 執行時環境。

SWT

與 AWT 的概念相比,SWT 是一個低階的 GUI 工具包。JFace 是一組用來簡化使用 SWT 構建 GUI 的增強元件和工具服務。SWT 的構建者從 AWT 和 Swing 實現中學習了很多經驗,他們試圖構建一個集二者優點於一體而沒有二者的缺點的系統。從很多方面來說,他們已經成功了。

SWT 也是基於一個對等體實現的,在這一點上它與 AWT 非常類似。它克服了 AWT 所面臨的 LCD 的問題,方法如下:定義了一組控制元件,它們可以用來構建大部分辦公應用程式或開發者工具,然後可以按照逐個主機的原則,為特定主機所沒有提供的控制元件建立模擬控制元件(這與 Swing 類似)。對於大部分現代主機來說,幾乎所有的控制元件都是基於本地對等體的。這意味著基於 SWT 的 GUI 既具有主機外觀,又具有主機的效能。這樣就避免了使用 AWT 和 Swing 而引起的大部分問題。特定的主機具有一些低階功能控制元件,因此 SWT 提供了擴充(通常是模擬的)版本(通常使用 “C” 作為名字中的第一個字母),從而可以產生更一致的行為。

在對等體工作方式上,SWT 與 AWT 不同。在 SWT 中,對等體只是主機控制元件上的一些封裝程式而已。在 AWT 中,對等體可以提供服務來最小化主機之間的差異(就是在這裡,AWT 碰到了很多行為不一致的問題)。這意味著 SWT 應用程式實際上就是一個主機應用程式,它必然會全部繼承主機的優點和缺點。這還意味著 SWT 不能完全實現 WORE 的目標;它更像是一種 WOTE 解決方案。這就是說,SWT 儘管不如 Swing 那麼優秀,但是它在建立可移植解決方案方面是很傑出的。

SWT 不支援 GUI 控制元件的自動銷燬。這意味著我們必須顯式地銷燬所建立的任何控制元件和資源,例如顏色和字型,而不能利用 API 呼叫來實現這種功能。這種工作從某種程度上來說得到了簡化,因為容器控制了其子控制元件的自動銷燬功能。

使用 SWT 只能自頂向下地構建 GUI。因此,如果沒有父容器,子控制元件也就不存在了;通常父容器都不能在以後任意改變。這種方法不如 AWT/Swing 靈活。控制元件是在建立時被新增到父容器中的,在銷燬時被從父容器中刪除的。而且 SWT 對於 style 位的使用只會在構建時進行,這限制了有些 GUI 控制元件的靈活性。有些風格只是一些提示性的,它們在所有平臺上的行為可能並不完全相同。

與 Swing 類似,SWT 元件也不是執行緒安全的,這意味著您必須要關心在應用程式中是哪個執行緒對 GUI 進行了更新。如果在使用執行緒時發生了錯誤,就會丟擲異常。我認為這比不確定的 Swing 方法要好。有一些工具可以幫助管理執行緒的問題。

如果所支援的作業系統提供了可訪問性服務,那麼 SWT GUI 通常也就具有很好的可訪問性。當預設資訊不夠時,SWT 為程式設計師提供了一個基本的 API 來指定可訪問性資訊。

SWT 提供了一個有限的圖形環境。到目前為止,它對於 Java2D 和 Java3D 的支援還不怎麼好。Eclipse 使用一個名為 Draw2D 的元件提供了另外一種單獨的圖形編輯框架(Graphical Editing Framework,GEF),它可以用來建立一些繪圖應用程式,例如 UML 建模工具。不幸的是,GEF 難以單獨(即在整個 Eclipse 環境之外)使用。

與 AWT 和 Swing 不同,SWT 和 JFace 並不是 Java 技術的標準配置。它們必須單獨進行安裝,這可以當作是 Eclipse 安裝的一部分,也可以當作是單獨的庫進行安裝。Eclipse 小組已經使它的安裝變得非常簡單,並且 SWT 可以與 Eclipse 分開單獨執行。所需要的 Java 檔案檔案(JAR)和動態連結庫(DLL)以及 UNIX® 和 Macintosh 上使用的類似庫可以從 Eclipse Web 站點上單獨下載。JFace 庫需要您下載所有的 Eclipse 檔案,並拷貝所需要的 JAR 檔案。在下載所需要的檔案之後,我們還需要將這些 JAR 檔案放到 Java CLASSPATH 中,並將 DLL 檔案放到系統 PATH 中。

SWT本身僅僅是Eclipse組織為了開發Eclipse IDE環境所編寫的一組底層圖形介面 API。或許是無心插柳,或是有意為之,至今為止,SWT無論是在效能和外觀上,都超越了SUN公司提供的AWT和SWING。目前Eclipse IDE已經開發到了2.1版本,SWT已經十分穩定。這裡指的穩定應該包含兩層意思:

一是指效能上的穩定,其中的關鍵是源於SWT的設計理念。SWT最大化了作業系統的圖形構件API,就是說只要作業系統提供了相應圖形的構件,那麼SWT只是簡單應用JNI技術呼叫它們,只有那些作業系統中不提供的構件,SWT才自己去做一個模擬的實現。可以看出SWT的效能上的穩定大多時候取決於相應作業系統圖形構件的穩定性。

另一個穩定是指SWT API包中的類、方法的名稱和結構已經少有改變,程式設計師不用擔心由於Eclipse組織開發進度很快(Eclipse IDE每天都會有一個Nightly版本的釋出),而導致自己的程式程式碼變化過大。從一個版本的SWT更新至另一版本,通常只需要簡單將SWT包換掉就可以了。

SWT採用了一種簡單而直接的方式去適應本地GUI系統對執行緒的要求:在SWT中,通常存在一個被稱為"使用者執行緒"的唯一執行緒,只有在這個執行緒中才能呼叫對構件或某些圖形API的訪問操作。如果在非使用者執行緒中程式直接呼叫這些訪問操作,那麼SWTExcepiton異常會被丟擲。但是SWT也在*.widget.Display類中提供了兩個方法可以間接的在非使用者執行緒的進行圖形構件的訪問操作,這是通過的syncExec(Runnable)和asyncExec(Runnable)這兩個方法去實現的。

JFace

JFace與SWT的關係好比Microsoft的MFC與SDK的關係,JFace是基於SWT開發,其API比SWT更加易於使用,但功能卻沒SWT來的直接。比如下面的程式碼應用JFace中的MessageDialog開啟一個警告對話方塊:

MessageDialog.openWarning(parent," Warning"," Warning message");

如果只用SWT完成以上功能,語句不會少於30行!

JFace原本是為更加方便的使用SWT而編寫的一組API,其主要目的是為了開發Eclipse IDE環境,而不是為了應用到其它的獨立應用程式。因此在Eclipse 2.1版本之前,很難將JFace API完整的從Eclipse的核心API中剝離出來,總是要多多少少匯入一些非JFace以外的Eclipse核心程式碼類或接口才能得到一個沒有任何編譯錯誤的JFace開發包。但目前Eclipse組織似乎已經逐漸意識到了JFace在開發獨立應用程式起到的重要作用,在正在開發的2.1版本中,JFace也開始變成了和SWT一樣的完整獨立的開發包,只是這個開發包還在變動中(筆者寫本文時,應用的Eclipse2.1M3版本)。JFace開發包的包字首是以org.eclipse.jface開頭。JAR包和原始碼也和SWT一樣,也在${你的eclipse安裝路徑}/plugins路徑下去找。

對開發人員來說,在開發一個圖形構件的時候,比較好的方式是先到JFace包去找一找,看是不是有更簡潔的實現方法,如果沒有再用SWT包去自己實現。比如JFace為對話方塊提供了很好的支援,除了各種型別的對話方塊(比如上面用的MessageDialog,或是帶有Title欄的對話方塊),如要實現一個自定義的對話方塊也最好從JFace中的Dialog類繼承,而不是從SWT中的*.widget.Dialog繼承。

應用JFace中的Preference包中的類很容易為自己的軟體做出一個很專業的配置對話方塊。對於Tree、Table等圖形構件,它們在顯示的同時也要和資料關聯,例如Table中顯示的資料,在JFace中的View包中為此類構件提供了Model-View方式的程式設計方法,這種方法使顯示與資料分開,更加利於開發與維護。JFace中提供最多的功能就是對文字內容的處理。可以在org.eclipse.jface.text.*包中找到數十個與文字處理相關類。