歷史 |
回到上個世紀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的類是以共享系統庫的方式預加載的。
上述的比較總的來講是技術上的總結。相對其餘方面的因素也會影響你對一個工具集的選擇。例如,文檔,支持,學習曲線和社區等,但既然咱們關注的是技術層面,就不在這裏講的太多了。