SWT 和 JFace, 第 1 部分:如何創建簡單的 SWT 應用程序

 
在這篇 SWT 和 JFace 系列的第一篇文章中,可以瞭解如何使用 Java™、Eclipse 以及 SWT 和 JFace 庫創建簡單的 SWT 應用程序。 還可以瞭解如何使用基本的控件和佈局創建簡單的 SWT GUI。

可以使用標準窗口小部件工具箱(Standard Widget Toolkit,SWT)和 JFace 庫來開發用於 Eclipse 環境的圖形用戶界面,而且還可以將它們用於開發單獨的 GUI 本機應用程序。在本文中,我將介紹一些基本的 SWT(基本 GUI 對象的名稱)類型,並展示如何綜合使用它們來創建有用的應用程序。

關於 Eclipse、SWT 和 JFace

正如 Eclipse 的 Web 站點上所提到的,Eclipse 是一種通用工具平臺。它是一個開放的、可用於任何東西的可擴展 IDE,沒什麼特別之處,它爲工具開發人員提供了靈活性以及對軟件技術的控制。

Eclipse 爲開發人員提供了生產大量 GUI 驅動的工具和應用程序的基礎。而這項功能的基礎就是 GUI 庫 SWTJFace

SWT 是一個庫,它創建了Java 版的本地主機操作系統 GUI 控件。它依賴於本機實現。這意味着基於 SWT 的應用程序具有以下幾個關鍵特性:

  1. 它們的外觀、行爲和執行類似於“本機”應用程序。
  2. 所提供的窗口小部件(widget)反映了主機操作系統上提供的窗口小部件(組件和控件)。
  3. 主機 GUI 庫的任何特殊行爲都在 SWT GUI 中得到反映。

這些目標使得 SWT 不同於 Java 技術的 Swing,Swing 的設計目標是消除操作系統的差異。

SWT 庫反映了主機操作系統的基本窗口小部件。在許多環境下,這種方法太低級。JFace 庫有助於向 SWT 應用程序中添加大量服務。JFace 並沒有隱藏 SWT,它只是擴展了 SWT。正如您將在這一系列的後面部分中看到的,SWT 最重要的擴展之一是,將應用程序的數據模型與顯示及更改它的 GUI 隔離開來。

關於本系列

SWT 和 JFace 系列中包含一些描述使用 SWT 和 JFace 庫開發應用程序的基礎文章,這些庫是與基本的 Eclipse 軟件開發工具包(SDK)一起提供的。這一系列集中描述瞭如何使用 SWT 和 JFace 開發獨立的應用程序。不過,您所學的大部分知識都可以應用到在 Eclipse 工作臺中使用 SWT 當中。

我們將從具有有限功能的一些簡單的 GUI 開始,然後朝着有用的應用程序擴展。我們將介紹大多數標準、定製的 SWT 窗口小部件和許多 JFace 特性。在我們的討論中,至少包含一個使用該技術的例子。

本系列假定您熟悉 Java 語言和基於 Java 的開發,並且對 Java AWT 或 Swing GUI 工具包有一定的瞭解。

在開始之前,我需要介紹一些 SWT 術語:

  • Widget —— 基本的 SWT GUI 組件(類似於 Java AWT 中的 Component 和 Swing 中的 JComponent)。Widget 是一個抽象類。
  • Control —— 擁有操作系統的對等物的窗口小部件(換句話說,在操作系統中具有同一身份)。Control 是一個抽象類。
  • Composite —— 包含其他控件的控件(類似於 Java AWT 中的 Container 和 Swing 中的 JPanel)。
  • Item —— 其他控件包含的窗口小部件(該控件可能不是複合控件),比如列表和表。注意,包含一些項的控件很少包含其他控件,反之亦然。Item 是一個抽象類。

這些窗口小部件被安排在繼承層次結構中。參見圖 1、圖 2 和圖 3,瞭解它們是如何安排的。在圖 2 中,Basic1 類是來自本文的類,而其他所有類都是標準的 SWT 窗口小部件。


圖 1. SWT Widget 樹
SWT Widget 樹

圖 2. SWT Composite 樹
SWT Composite 樹

圖 3. SWT Item 列表
SWT Item 列表
安裝 SWT 和 JFace

請參閱 參考資料,從中尋找 Eclipse 的 Web 站點。請安裝 Eclipse,並使 SWT 庫在您的應用程序中可用:

  1. 選擇 Eclipse 主頁中的 Downloads,然後選擇您的平臺所需的 Eclipse 版本。接着,下載相關的 ZIP 文件。
  2. 將這個 ZIP 文件展開到一個高級目錄中(建議取一個“EclipseX.Y.Z”之類的名字,其中,X、Y 和 Z 是您所選擇的 Eclipse 版本)。
  3. 使用 DIR 命令或 Search 命令來查找 swt.jar 文件,並將它放置在您的 CLASSPATH 中(或者在 java -cp 命令中使用它)。
  4. 還要查找所有 SWT-*.DLL 文件,並確保能夠訪問它們(將它們所在的目錄放到 PATH 中,或者將這些 DLL 文件複製到 PATH 上已有的一個目錄中)。

其他平臺上的步驟與此類似。

注意,Eclipse 具有跨平臺特性(因此可以在許多操作平臺上運行),本文基於 Eclipse 的 Microsoft® Windows® 版本。因此,本文包含的每個例子都應該能夠不加任何更改地在其他平臺上使用。還要注意的是,本文是基於 Eclipse V3.0 的。Eclipse V3.1 中添加了少許 GUI 窗口小部件類型和特性。





回頁首


基本控件

幾乎所有 SWT GUI 都是從某些基礎部分開始創建的。所有 SWT 窗口小部件都可以在 org.eclipse.swt.widgetorg.eclipse.swt.custom 包中找到。(一些 Eclipse 插件還在其他包中提供了定製的窗口小部件。)窗口小部件包中包含一些基於操作系統控件的控件,而定製包中則包含一些超出操作系統控件集之外的控件。一些定製的軟件包控件類似於窗口小部件包中的控件。爲了避免命名衝突,定製控件的名稱都是以“C”開始的(例如,比較 CLabel 與 Label)。

在 SWT 中,所有控件(除了一些高級控件,比如 shell,將在後面進行討論)在創建的時候都必須有一個父控件(一個複合實例)。在創建的時候,這些控件被自動“添加”到父控件中,這與必須明確添加到父控件中的 AWT/Swing 中的控件有所不同,自動添加產生了一種“自上而下”地構造 GUI 的方法。這樣,所有控件都可以採用一個複合父控件(或者一個子類)作爲構造函數的參數。

大多數控件都有一些必須在創建時設置的標記選項。因此,大多數控件還有另外一個構造函數參數,我們通常稱之爲樣式,該參數提供了設置這些選項的標記。所有這些參數值都是 static final int,並且都是在 org.eclipse.swt 包的 SWT 類中定義的。如果不需要任何參數,則可以使用 SWT.NONE 值。





回頁首


標籤

標籤可能是最簡單的控件,標籤 被用於顯示純文本(沒有顏色、特殊字體或樣式的文本)或稱爲圖標的小圖像。標籤不接受焦點(換句話說,用戶不能通過 Tab 鍵或鼠標移動到標籤),因此,標籤無法產生輸入事件。

清單 1 展示瞭如何創建一個簡單的文本標籤。


清單 1. 創建一個帶文本的標籤
				
import org.eclipse.swt.widget.*;
 :
Composite parent = ...;
 :
// create a center aligned label
Label label = new Label(parent, SWT.CENTER);  
label.setText("This is the label text");

注意,該文本是採用不同於構造函數的單獨的方法設置的。這是所有 SWT 控件的一個典型象徵。只有父控件和樣式是在構造函數中設置的,其他所有屬性都是在已創建的對象上設置的。

由於平臺的限制,標準標籤控件不能同時擁有文本和圖標。爲了支持同時擁有文本和圖標,可以使用 CLabel 控件,如清單 2 中所示。


清單 2. 創建一個包含文本和圖像的標籤
				
import com.eclipse.swt.graphics.*;
import org.eclipse.swt.widget.*;
import org.eclipse.swt.custom.*;
 :
Composite parent = ...;
Image image = ...;
 :
// create a left aligned label with an icon
CLabel Clabel = new CLabel(parent, SWT.LEFT);  
label.setText("This is the imaged label text"");
label.setImage(image);





回頁首


文本

在標籤顯示文本的同時,您時常還想允許用戶插入文本。文本 控件就是用於此目的的。文本可以是單行的(一個文本字段),也可以是多行的(一個文本區域)。文本還可以是隻讀的。文本字段中沒有描述,因此,常常通過標籤控件處理它們,以確定它們的用途。文本控件還可以包含一個“工具提示”,提供關於控件用途的信息(所有控件都支持這一特性)。

清單 3 顯示瞭如何使用允許使用的有限數量的特性來創建一個簡單的文本字段。選擇默認文本是爲了便於擦除。


清單 3. 創建一個包含選定的默認文本和一個限制條件的文本
				
import org.eclipse.swt.widget.*;
 :
Composite parent = ...;
 :
// create a text field
Text name = new Text(parent, SWT.SINGLE);  
name.setText("<none>");
name.setTextLimit(50);
name.setToolTipText("Enter your name -- Last, First"); 
name.selectAll();  // enable fast erase





回頁首


按鈕

通常,您希望用戶指出應該何時進行某項操作。最常見的做法是使用按鈕 控件。存在以下幾種樣式的按鈕:

  • ARROW —— 顯示爲一個指向上、下、左、右方向的箭頭。
  • CHECK —— 已標記的複選標記。
  • FLAT —— 沒有凸起外觀的按鈕。
  • PUSH —— 瞬時按鈕(最常見的事件源)。
  • RADIO —— 具有排他性的粘性標記(sticky mark),其他所有單選按鈕都在相同的組中。
  • TOGGLE —— 一個粘性按鈕。

清單 4 創建了一個“Clear”按鈕:


清單 4. 創建一個按鈕
				
import org.eclipse.swt.widget.*;
 :
Composite parent = ...;
 :
// create a push button
Button clear = new Button(parent, SWT.PUSH);  
clear.setText("Clea&r");

名稱中的 & 導致利用緊接着的一個字母創建一個加速器,允許通過 Ctrl+<字母> 順序的方式按下按鈕(控件順序由主機操作系統決定)。

事件監聽器

通常,您可能想在選擇按鈕(特別是某種推式按鈕)的時候執行一些操作。您可以通過向該按鈕添加一個 SelectionListener(在 org.eclipse.swt.events 包中)做到這一點。當按鈕狀態發生改變時(通常是按鈕被按下),就會生成事件。清單 5 在單擊 Clear 按鈕時輸出一條消息。


清單 5. 按鈕事件處理程序
				
import org.eclipse.swt.events.*;
 :
// Clear button pressed event handler
clear.addSelectionListener(new SelectionListener() { 
    public void widgetelected(selectionEvent e) {
        System.out.println("Clear pressed!");   
    }
    public void widgetDefaultSelected(selectionEvent e) {
        widgetelected(e);
    }
});

此代碼使用了一個匿名的內部類,但您還可以使用指定的內部類或單獨的類作爲監聽器。多數包含兩個或更多方法的 ...Listener 類還有一個類似的 ...Adapter 類,這個類提供了一些空的方法實現,並且可以減少您需要編寫的代碼數量。例如,還有一個 SelectionAdapter 類,這個類實現了 SelectionListener

注意,在這些方法中執行的操作必須快速完成(通常不足一秒時間),或者說 GUI 的反應將是遲鈍的。更長時間的操作(比如訪問文件)需要單獨的線程,但那是以後某期文章的主題。





回頁首


複合控件

至此,我們已經討論了一些單獨的控件。在多數 GUI 中,許多控件被組合在一起以提供豐富的用戶體驗。在 SWT 中,這種組合是通過 Composite 類實現的。

複合控件可以在任何級別上進行嵌套,並且可以混合和匹配控件,將它們作爲子控件進行組合。這樣做可以極大地減少 GUI 開發的複雜性,併爲 GUI 代碼重用(通過封裝內部 GUI)創造了機會。複合控件可以是有邊界的,並且這些邊界很容易在視覺上產生混淆,或者它們也可以是無邊界的,無縫集成到更大的組中。

清單 6. 創建一個有邊界的複合控件。


清單 6. 創建一個有邊界的複合控件
				
import org.eclipse.swt.widget.*;
 :
Composite parent = ...;
 :
Composite border = new Composite(parent, SWT.BORDER);

除了邊界之外,Group 複合子類還支持標題。在定義排他性按鈕集合時,組通常被用來包含單選類型的按鈕。

清單 7 創建了一個有邊界的組。


清單 7. 創建一個有邊界的組
				
import org.eclipse.swt.widget.*;
 :
Composite parent = ...;
 :
Group border = new Group(parent, SWT.SHADOW_OUT);
border.setText("Group Description");

shell

shell 是一種可能沒有父複合控件的複合控件(框架或窗口);此外,它還有一個作爲父控件的 Display,這通常也是默認設置。shell 有很多種樣式,但最常見的樣式是 SWT.SHELL_TRIMSWT.DIALOG_TRIM。shell 可以是模態的,也可以是非模態的。模態 shell 常常用於對話框,防止父 GUI(如果有的話)在關閉子 shell 之前被處理。

清單 8 創建了一個框架樣式的頂級非模態 shell。


清單 8. 創建一個頂級 shell
				
import org.eclipse.swt.widget.*;
 :
Shell frame = new Shell(SWT.SHELL_TRIM);
 :

shell 可以有子 shell。這些子 shell 是與父 shell 相關的獨立桌面窗口(也就是說,如果父 shell 關閉,那麼其所有子 shell 也將關閉)。

清單 9 創建了一個對話框樣式的子 shell。


清單 9. 創建一個對話框 shell
				
:
Shell dialog = new Shell(frame, SWT.DIALOG_TRIM);
 :

參見圖 4 中具有 SWT.SHELL_TRIMSee 的 shell,以及圖 5 中具有 SWT.DIALOG_TRIM 的 shell,瞭解這些值如何影響 shell 的整潔性。


圖 4. 具有 SWT.SHELL_TRIM 的 shell
具有 SWT.SHELL_TRIM 的 shell

圖 5. 具有 SWT.DIALOG_TRIM 的 shell
具有 SWT.DIALOG_TRIM 的 shell




回頁首


佈局管理器

複合控件常常包含多個控件。可以使用以下兩種方法安排這些控件:

  1. 絕對定位 —— 爲每個控件設置明確的 X 和 Y 位置,並通過代碼設置一定的寬度和高度。
  2. 託管定位 —— 每個控件的 X、Y、寬度和高度都是通過 LayoutManager 設置的。

在多數情況下,應該選擇使用 LayoutManagers,因爲很容易調整它們來適應可變大小的 GUI。SWT 也提供了一些佈局管理器供您使用;在這一期的系列文章中,我們將討論兩種基本的佈局管理器:FillLayoutGridLayout。在這兩種情況下,每當重新設置複合控件的大小,都需要進行定位。

一些佈局管理器常常是專爲某一個複合控件分配的。一些佈局管理器只使用它們自身的參數就可以控制,而另一些佈局管理器還需要其他參數 —— LayoutData,該參數是在它們管理的複合控件中的每個控件上指定的。

FillLayout

FillLayout 以行或列的形式安排控件。每個控件所設置的大小將與填充該複合控件所需的寬度和高度相同,在這些控件之間,空間是平均分配的。一種特殊情況是:在僅有一個子控件時,該控件的大小被設置爲填充整個父複合控件的大小。

清單 10 使用一個列 FillLayout 創建了一個複合控件。


清單 10. 使用 FillLayout 創建一列控件
				
import org.eclipse.swt.widget.*;
import org.eclipse.swt.layouts.*;
 :
Composite composite = ...;
FillLayout fillLayout = new FillLayout(SWT.VERTICAL);
composite.setLayout(fillLayout);

GridLayout

GridLayout 提供了一個功能更強大的佈局方法,該方法類似於使用 HTML 表的方法。它創建了 2-D 網格的單元格。可以將控件放置在一個或多個單元格中(可以稱之爲單元格跨越)。單元格的大小可以是相等的,或者是網格寬度或高度的某個給定可變百分比。可以將控件添加到某一行的下一個可用列中,如果這一行中沒有更多的列,那麼該控件將移動到下一行的第一列中。

清單 11 創建了一個複合控件,該控件有兩行和兩個列,其中包含兩個已標記的文本字段。這些列可以有不同的寬度。


清單 11. 創建一個控件表
				
import org.eclipse.swt.widget.*;
import org.eclipse.swt.layouts.*;
 :
Composite composite = ...;
GridLayout gridLayout = new GridLayout(2, false);
composite.setLayout(gridLayout);
Label l1 = new Label(composite, SWT.LEFT);
l1.settext("First Name: ");
Text first = new Text(composite, SWT.SINGLE);
Label l1 = new Label(composite, SWT.LEFT);
l2.setText("Last Name: ");
Text last = new Text(composite, SWT.SINGLE);

GridData

考慮一下這種情況:您需要指定每個控件如何使用其單元格中的剩餘空間。爲了給每個單元格提供這種精確控制,添加到 GridLayout 的託管複合控件的控件可以擁有 GridData 實例(LayoutData 的子類)。

清單 12 設置了這些文本字段,以便採用所有可用的剩餘空間(根據前面的清單)。


清單 12. 配置一個擴展到所有可用空間的佈局
				
first.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
last.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));





回頁首


構建一個運行程序

現在是時候來看一下我們已經在簡單的可執行例子 Basic1 中討論過的所有 SWT 控件了。請參閱 參考資料,以獲得該應用程序的完整源代碼。

SWT GUI 需要一個已配置好的環境來運行。這個環境是通過一個顯示實例提供的,該實例提供了對主機操作系統顯示設備的訪問。這個顯示實例允許您處理每個用戶輸入(鼠標或鍵盤)來處理您的 GUI。

清單 13 創建了一個環境和一個 GUI,並顯示了這個 GUI。


清單 13. 創建一個 GUI 應用程序並啓動它
				
import org.eclipse.swt.widget.*;
 :
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Shell Title");
// *** construct Shell children here ***
shell.open();       // open shell for user access
// process all user input events
while(!shell.isDisposed()) {
   // process the next event, wait when none available
   if(!display.readAndDispatch()) {
       display.sleep();
   }
}
display.dispose();  // must always clean up

此代碼創建了一個類似於圖 6 的窗口。


圖 6. 示例應用程序
SWT 應用程序




回頁首


結束語

SWT 和 JFace 系列的第一期中,我們介紹了大多數基本 SWT 窗口小部件控件:標籤、文本、按鈕、複合控件和 shell。這些控件,與顯示類(display class)相結合,允許創建全功能的 GUI。

本系列的第 2 部分將展示如何創建菜單,以及如何使用其他輸入控件和信息顯示控件,比如列表、樹和表等。






回頁首


下載

描述 名字 大小 下載方法
Basic1 Java source os-Basic1.java 6.39 KB HTTP
關於下載方法的信息


參考資料

  • 您可以參閱本文在 developerWorks 全球站點上的 英文原文

  • 單獨使用 JFace 和 SWT”(developerWorks, 2003 年 1 月)介紹了一些主要的 JFace 類(和少量 SWT 窗口小部件),以及一些技巧、竅門和設計問題。

  • Sun Microsystems Web 站點 是開始查找 Java 開發信息的一個好地方。您將在那裏找到一些新聞、論壇、文章和下載。

  • Sun 公司的 Java Foundation Classes (JFC/Swing) 包含一些到有關 JFC/Swing 的下載、技術信息、how-to 文章和新聞的鏈接。

  • Sun 公司的 Swing Connection 是適合那些對 Swing 感興趣的人們的新聞和更新頁面。

  • Sun 公司爲 Java 用戶 提供了一個 Web 站點。該站點中包含一些遊戲、預覽和其他 Java 技術展示,還包含一些下載。

  • Eclipse In Action: A Guide for Java Developers (Independent Publishers Group, 2003)是使用 Eclipse 的 Java 編程人員必須閱讀的書籍。

  • 瀏覽 developerWorks 上的所有 Eclipse 專欄

  • 獲得 Eclipse 的最新版本,Eclipse 是用於應用程序開發的一個開源 IDE。

  • 請在本文附帶的 Eclipse 討論論壇 中與作者和其他讀者分享您對本文的看法。

  • 要了解關於 Eclipse 的更多信息,請參閱 eclipse.org。您將在那裏找到技術文檔、how-to 文章、教育、下載、產品信息和其他更多信息。

  • 請訪問 developerWorks 的 開源技術專區,以獲得大量 how-to 信息、工具和項目更新,這些信息有助於您開發開源技術和將它們應用到 IBM 的產品中。

  • 利用 IBM 試用軟件 改革您的下一個開源開發項目,這些軟件可以通過下載或從 DVD 中獲得。

  • 在 Developer Bookstore 的開源技術專區中可以找到數百本 打折銷售的關於開源主題的書籍

  • 通過參與 developerWorks blogs 加入 developerWorks 社區。


關於作者

作者照片

Barry Feigenbaum 博士是 IBM Worldwide Accessibility Center 中的一員,在那裏,他是幫助殘疾人訪問 IBM 產品的團隊的成員之一。Feigenbaum 曾出版過幾本書,發表過一些文章,擁有幾項專利,並曾在 JavaOne 這樣的行業大會上發表演講。他是位於奧斯汀的德克薩斯州大學和其他學校的計算機科學系的兼職助理教授。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章