The Standard Widget Toolkit(SWT) introduction

Java 的 GUI library 一直是它的弱項。從早期的 Applet 紅了以後,AWT 這個破破的東東就一直撐撐撐到 1.2 出了以後才有更強的 Swing 來取代它。在這期間,M$ 也出過 AFC(Application Fundation Class),觀念類似 Swing,想以 Pure Java 來實作所有的 GUI library,只可惜,實在是太 heavy 了。

Java 因為 VM 速度實在是太快了,所以許多的 library 都是以 pure java 實作的,雖然效率不輸 C 程式太多,但是在記憶體的使用上,一旦 class 多了起來,佔用的的空間就會比 C code 大上許多(這有許多的因素,像是JIT、class metadata…),這是相當可惜的地方。

所以上面所說的 heavy,是指所需要佔用的資源。雖然在 SUN 的文件中以 lightweight component 代表 Swing 中的 GUI 元件,但其實它一點也不 lightweight…

再 者,作業系統中已經做過的事,VM 再去做一次,這實在是太浪費資源了(我們電腦中的硬碟空間、執行時要消耗的記憶體空間、下載 VM 時所用的頻寬、SUN 裡 Swing 開發小組成員的青春…)。而且,這些 Java 寫成的元件還沒法跟系統中那些有很一致的行為,對一般的時用者而言實在是很不能接受。我的幾個朋友就是因為 Swing 元件長得有點像 native GUI 又不太像的關係而不想接受它…

我玩 Swing 也玩了好一陣子,許多的設計方法都是從它那裡學來的。基本上,我覺得 Swing 的架構設計得還不錯,使用起來非常的簡單。要做出自己的 GUI 元件或是新的 Skin 都不是難事。只可惜…真的太 heavy 了。在 Swing 中開一個 frame 就要吃掉 13 MB(以前要 20 多 MB,SUN 真的是很會 tune 東 東) 了,SWT 的 Shell 開起來只要 9 MB。當然,有人會說:SWT 只是一個 GUI library,而 Swing 則有 MVC 的架構。是沒錯,但是 SWT + JFace 一樣能達到 MVC 的架構,而且還提供 framework 簡化程式的設計,後者 Swing 就沒有了。但,SWT + JFace 所需要的記憶體還是小於 Swing 所需的…當不想使用 JFace 時還可以將它拿掉,這是 Swing 所無法達到的功能。

還有,SWT 因為不斷的加強與系統互動的程度,現在它在各種平臺上都可以使用 Browser 元件(以 Java class 包過的 native browser,在 windows 裡是 IE,在 linux 裡是 mozilla)來顯示 HTML 文件。剪貼簿跟 Drag & Drop 更是 Swing 的弱項,唉~Swing,我曾是妳的愛用者,但是你的痴肥跟不長進真是讓我無法再接受妳呀!

說了一堆廢話,哈!來看看 SWT 程式怎麼寫吧!

`
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Main
{

/**

  • @param args
    */
    public static void main(String[] args)
    {
    Display display = Display.getDefault();
    Shell shell = new Shell(display);
    shell.setText("Test SWT");
    shell.pack();
    shell.open();

while(! shell.isDisposed()) {
if(! display.readAndDispatch()) {
display.sleep();
}
}

shell.dispose();
display.dispose();
}

}
`

就這麼簡單。下面是 Swing 的版本

`
import javax.swing.JFrame;

public class Main
{

/**

  • @param args
    */
    public static void main(String[] args)
    {
    JFrame frame = new JFrame("Test Swing");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
    }

}
`

功能都一樣,看起來 Swing 簡單些,因為不需要有 event loop,library 本身就幫你完成這個工作了。這裡只是用來比較一下兩個 library 的風格,之後就不會再有 Swing 的例子了。

在 Swing 中,大部份的事情 library 都會幫你完成,像是上面所說的 event loop。Component 的建立也不會有相依性,也就是說每個 GUI 元件建立的順序可以隨你高與任意安排。在元件使用完以後只要搞得它不被使用者看見,接下來等 GC 回收即可,很方便,但在資源的管理上也沒有什麼規則,有可能寫出來的程式會有 memory leak。

SWT 則是被定義為提供最基本 GUI 功能的 library。一些很炫的 skin 功能它都沒有,除非所在的平臺有提供的話才會繼承而來。GUI 的建立上,parent 要先於 child 產生(parent 可看做 Swing 中的 Container。child 則可能是 Component)。Event loop 對使用者而言是可見的,每一個要產生 GUI 元件並處理事件的 thread 都要寫好這一小段 code。再者,SWT 大量的使用 native GUI,所以必須在用完後確實的釋放 peer(例如 Button 元件,除了 java 寫成跑在 JVM 中的 class 外,還有在 JVM 外 native environment 中所佔用、配置的資源,這些資源在 AWT 中叫 peer)。因為 java VM spec 中並未規定物件在回收時 finalize() 一定要被呼叫,所以 SWT 只得規定元件在使用完畢後必須要呼叫 dispose() 釋放資源。雖然不是很方便,但會讓使用者對於資源的使用再多加考慮過。

寫過 GUI 程式的人應該看了就大概能瞭解上面的 code 在做些什麼。主要完成的事情就是

  1. 建立主視窗,在 Swing 中這個 class 叫 JFrame,在 SWT 叫 Shell

  2. 設定視窗標題

  3. 調整視窗大小

  4. 顯示視窗

Swing 版還必須要設定當 frame 關閉時結束程式,否則 default 的行為是看起來 frame 是 close 了,可是 VM 其實還在 run。SWT 則在視窗開啟後,要有個 event loop 不停的 read & dispatch event,直到 shell 被 dispose 後才結束程式。

Swing 程式如果要執行很簡單,就跟一般的 java 程式一樣,沒什麼特殊的。但 SWT 的程式則必須將 swt.jar 及 SWT 的 native library 放置目錄告訴 VM。以下是一個在 windows 中執行的範例,目錄名稱請自行修改:
java -cp .;c:\swt-3.1 -Djava.library.path=c:\swt-3.1 Main
至於 SWT 要去哪找勒?如果你有 eclipse 的話,安裝目錄中就有了(不然,eclipse 是怎麼跑起來的?),或者你可以到 eclipse 的網站上抓也是可以滴!網址如下:
http://www.eclipse.org/downloads/index.php

晚了…先醬吧,睡覺去了。