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

關于 Eclipse、SWT 和 JFace

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

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

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

  • 它們的外觀、行為和執行類似于“本機”應用程序。
  • 所提供的窗口小部件(widget)反映了主機操作系統上提供的窗口小部件(組件和控件)。
  • 主機 GUI 庫的任何特殊行為都在 SWT GUI 中得到反映。
      這些目標使得 SWT 不同于 Java 技術的 Swing,Swing 的設計目標是消除操作系統的差異。

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

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

    1. Widget —— 基本的 SWT GUI 組件(類似于 Java AWT 中的 Component 和 Swing 中的 JComponent)。Widget 是一個抽象類。
    2. Control —— 擁有操作系統的對等物的窗口小部件(換句話說,在操作系統中具有同一身份)。Control 是一個抽象類。
    3. Composite —— 包含其他控件的控件(類似于 Java AWT 中的 Container 和 Swing 中的 JPanel)。
    4. Item —— 其他控件包含的窗口小部件(該控件可能不是復合控件),比如列表和表。注意,包含一些項的控件很少包含其他控件,反之亦然。Item 是一個抽象類。
        這些窗口小部件被安排在繼承層次結構中。參見圖 1、圖 2 和圖 3,了解它們是如何安排的。在圖 2 中,Basic1 類是來自本文的類,而其他所有類都是標準的 SWT 窗口小部件。

        圖 1. SWT Widget 樹
        SWT Widget 樹

        圖 2. SWT Composite 樹
        SWT Composite 樹

        圖 3. SWT Item 列表
        SWT Item 列表
         
        注意,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 也提供了一些布局管理器供您使用;在這一期的系列文章中,我們將討論兩種基本的布局管理器:FillLayout 和 GridLayout。在這兩種情況下,每當重新設置復合控件的大小,都需要進行定位。

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

        FillLayout

        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。
      • 作者:http://www.zhujiangroad.com
        來源:http://www.zhujiangroad.com
        北斗有巢氏 有巢氏北斗