kooyee ‘s blog

          開源軟件, 眾人努力的結晶, 全人類的共同財富
          posts - 103, comments - 55, trackbacks - 0, articles - 66
             :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          [SWT] SWT簡介

          Posted on 2007-07-13 22:06 kooyee 閱讀(1228) 評論(0)  編輯  收藏 所屬分類: GUI骨衣
           

          Eclipse In Action - 附錄D. 介紹SWT- -

                                                

          《Eclipse In Action》是一本面向Eclipse初學者的教程,對Java開發有興趣的人也可以讀一讀。
          筆者參與了該書的翻譯工作,并同步發布譯稿,希望各位指正。

          附錄D. 介紹SWT


          翻譯:Addone Squid[天堂魷魚](addone@gmail.com


            本附錄介紹了標準窗口小部件工具包(SWT)并特別介紹了:

          • SWT是什么
          • SWT的體系結構
          • SWT和事件、線程
          • 如何運行SWT代碼

            SWT是由IBM開發的,作為抽象窗口工具包(AWT)和Swing的替代品的一種工具包。IBM的目標是創建一種GUI工具包,其觀感和行為都像是系統中通常的窗口小部件,并且性能上也具有相同的速度。在本附錄中,我們會觀察AWT和Swing的行為,并和IBM采取的方法相比較。然后,我們將討論如何使用SWT,指出在使用中比較重要的概念和問題。

          D.1 什么是標準窗口小部件工具包?


            Eclipse技術概述(http://www.eclipse.org/whitepapers/eclipse-overview.pdf)將SWT描述為一種“與本地窗口系統結合但使用操作系統無關的API的窗口小部件集及圖形庫”。在深入分析這種表述之前,讓我們來看看在Java 1.0版本中提供的第一個圖形API:抽象窗口工具包(AWT)。AWT提供了一套API來構建如標簽、文本框、按鈕、列表和菜單之類的圖形組件,并指派操作系統來提供這些組件的特定實現。當你構建一個文本框時,操作系統構造它自己的文本框并顯示在程序窗體中--Windows上的Java文本框看起來就像一個Windows文本框,而Macintosh上的Java文本框看起來就像一個Macintosh文本框。
            AWT的問題是Sun僅僅實現了在Java支持的所有平臺中共有的那些窗口小部件。為了解決這個問題,Sun和Netscape合作引入了Swing,這是創建完全跨平臺的窗口小部件集的一次嘗試。為了達到這個目標,他們用Java來編寫所有的東西,而不是指派給操作系統。這種方法讓Java在界面方面變得更有用,但代價是:

          • 這些控件和它們運行其上的平臺的外觀并不相符。
          • 相對于本地實現來說,這些控件的性能要差得多。

            Sun試圖通過為每種操作系統都開發被稱為“可插入式觀感”的東西來解決第一個問題。 然而,盡管這種方法解決了部分問題,Sun卻無法跟上操作系統的更新。比如,一種Windows的觀感在Windows 95、Windows 98、Windows ME、Windows 2000和Windows XP上看起來都一樣,而本地程序則會依賴于運行的是哪個版本,看起來會不一樣。
            Sun已經在性能問題上取得了很大進展,但一個模擬組件終究永遠也不可能和本地等價組件具有同樣好的性能。在JVM中總會存在一個翻譯過程,以將模擬組件翻譯為一個本地描繪的指令集。
            在Eclipse的開發過程中,IBM研發了針對這個問題的一種新方法,這是Sun的兩種方法的某種混合。SWT是一種通過Java本地接口(JNI)來訪問本地控件的窗口小部件集。只有在特定的操作系統上不存在的少數幾個控件才會進行模擬。這種方法的缺陷是,在Eclipse/SWT部署的每個平臺上,都需要有本地庫。然而好處是,程序的外觀和性能都和本地程序一樣。并且,從Eclipse的2.1版開始,在大多數桌面操作系統和Pocket PC上都支持SWT。

          D.2 SWT體系結構


            在談了一些關于SWT是什么的問題后,讓我們用圖形來再看看它。如圖D.1所示,SWT由三個基本組件組成:一個本地庫,負責與操作系統通訊;一個顯示類,作為SWT與GUI平臺通訊的接口;一個Shell類,作為程序的頂層窗口,可以容納窗口小部件(Widget)(控件組件的另一種說法)。

            在我們繼續之前,讓我們來研究一下我們剛剛引入的一些術語:

          • 顯示(Display)--想象顯示類的最好方式是把它當作一位管家。它執行所有重要的任務而使得你不必去管他們。這個類所做的最重要的工作之一是將本地平臺事件和適宜在SWT中使用的那些進行互譯。在你開發自己的程序的時候,你通常不需要對顯示類做些什么,只需在創建其他所有窗口前先創建它。
          • Shell--從根本上說,一個用戶看到的窗口是被操作系統的窗口管理器最終控制的。Shell被用作兩種不同類型的窗體。第一種是你的程序的頂層窗體,你的GUI的其它部分在其上構建。在這種情況下,Shell是作為顯示類的子類來創建的。另一種類型是一個窗體是其他窗體的子窗體,比如對話框。這種情況下,該Shell作為其父窗體的那個Shell的子類。
          • 窗口小部件(Widget)--這個術語意指控件(Control)組件(Composite)。你會發現,在SWT文檔的各處,這三個術語是交替使用的。簡單說來,一個窗口小部件就是可以放置在其他窗口小部件中的一個GUI對象。
          • 控件(Control)--具有操作系統對應物的GUI項。例如,一個按鈕,文本區域,或者菜單。
          • 組件(Composite)--一個可以擁有子窗口小部件的窗口小部件,比如工具欄和樹。最好的例子是canvas,你可以利用它,在使用不同布局的各種子canvas的輔助下構造復雜的用戶界面。

            SWT體系結構是設計來模擬平臺程序結構的,所以它對于窗口小部件創建和資源清理有很重要的影響。

          D.2.1 窗口小部件創建

            當你在SWT中創建一個控件的時候,你還需要考慮它是如何在底層操作系統中被創建的。每個控件都有一個相似的構造函數來接受兩個參數:第一個指定其父窗口小部件,第二個指定此窗口小部件的樣式。這對于許多操作系統的工作方式來說都是必要的。當該SWT對象被創建時,操作系統的對應對象也被創建了,而它需要知道自己的父對象是哪個。對于許多窗口小部件的樣式設置來說也是一樣的。一旦它們被創建了,其樣式就不能修改了。(所謂樣式就是一種有關窗口小部件外觀的對操作系統的示意。比如,當你創建了一個按鈕,樣式就定義了其類型:單選按鈕,普通按鈕,復選按鈕等等。)

          D.2.2 資源清理

            通常,當你使用Swing(或AWT)的時候,你只需創建你的窗口小部件、圖像、字體等等而無需關注它們的清理,因為你知道當垃圾回收器運行時JVM會處理它們的。然而,當你使用SWT時,你必須多加注意你對操作系統GUI資源的使用,因為只有有限的資源可用。
            當你在SWT中創建了一個基于資源的對象(例如顏色、鼠標指針、字體或圖像)時,你必須清理它。如果你不清理那些你不再需要的東西,就會發生資源泄漏,而你會在這種狀況下結束:不管是你的還是操作系統中運行著的其他程序,都將無法再創建任何對象。
            以下代碼片段分配了一個顏色(Color)資源然后清理了它:

            
          Color blue = new Color (display, 00255);
            blue.dispose();

          D.3 SWT與事件


            你在所有SWT程序中都會看到的最常用的代碼段如下:

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

            這通常被稱為信息泵事件調度循環。它的工作是當頂層窗口打開時接收來自操作系統的事件(比如,用戶在移動鼠標),把它們調度到合適的SWT窗口小部件中,然后休眠直至有其他事件需要處理。在你的程序中,你需要至少有一個這樣的東西,否則你的程序將無法接收操作系統的任何事件,這會讓用戶不大高興。
            這個方法和AWT和Swing所使用的很不一樣,后者為開發者隱藏了這種機制。這在SWT中沒有隱藏,因為如果你編寫SWT代碼并作為Eclipse插件的一部分,你根本不需要一個信息泵--你默認使用了由工作臺提供的那個。
            剩余的事件處理機制和AWT和Swing所用的差不多。大量的基本事件類型以及它們各自的偵聽器(Listener)、適配器(Adapter)都在包org.eclipse.swt.events中定義。參閱在線文檔可以獲得完整列表。以下代碼段演示了如何創建一個事件偵聽器以及如何將其加入到一個對象中:

            Button button = new Button(display, SWT.PUSH);
            button.addSelectionListener(new SelectListener()
            {
              public void widgetDefaultSelected( SelectionEvent e ) {}
              public void widgetSelected( SelectedEvent e )
              {
                System.out.println("Button Pressed");
              }
            });

            不熟悉事件處理的人不必擔心,這很簡單。如前所述,一個事件關聯著一個諸如用戶移動鼠標或者窗體被最大化之類的動作。對于每種可以接收的事件的類型,都有一個稱為偵聽器的接口。一個偵聽器就是一個類,它知道如何處理特定事件并且還會做些有用的事情。要想創建一個偵聽器類,你需要創建一個類來實現那個與你要處理的事件相符的特定的偵聽器接口。
            觀察前面的代碼段可知,我們關注的是SelectionEvent,它在點擊按鈕時發出。如果你在Javadoc中查看該事件,你會看到正確的偵聽器是SelectionListener。為了將一個偵聽器添加到一個窗口小部件類,你調用它的一個addXXXListener()方法,正如前面代碼中用到的addSelectionListener()

          提示
          與其花時間重復Javadoc中所說的東西,我們建議你查看在線幫助。在那里你可以找到一份關于可用事件類型的完整清單,并且還包括了它們以及處理(或生成)那些事件的窗口小部件的描述。要查看該幫助,選擇[幫助]->[幫助內容]->[平臺插件開發者指南]->[程序員指南]->[標準窗口小部件工具箱]->[窗口小部件]->[事件]。

          D.4 SWT與線程


            當你使用SWT創建一個SWT程序時,要考慮的一個重要因素就是所有的窗口小部件是如何與線程交互的。如果你熟悉Swing和AWT編程,那么以下內容會比較熟悉,不過某些重要的差異還是需要注意的。
            一個被稱為用戶界面線程的單一的重要線程負責處理事件,調度它們到合適的窗口小部件,以及進行窗體描繪。沒有了它,你的程序將無法做任何事情。你可能認為我們過去說過一些這方面的內容,我們的確曾經說過。
            在AWT和Swing中,用戶界面線程或事件處理線程對開發者是隱藏的。而在SWT中,創建消息泵的線程就成了用戶界面線程。這個設計決定使得要將SWT插件插入Eclipse中變得可能。與Sun的方法背離的另一點是,SWT的設計允許擁有多于一個的事件調度線程。(這個功能極少用到,我們提到它只是為了完整起見。)
            主線程就是用戶界面線程,所以你不該執行任何復雜的或耗時的任務(如數據庫訪問)或者其他會阻塞線程的任務。相反的,你應該轉到其他線程去執行那些操作。不這么做的話,將會嚴重影響你的用戶界面的響應能力并且會給用戶帶來不便,這永遠不是件好事。與此相關的事實就是,唯一允許調用SWT窗口小部件而不會引發SWTException異常的線程就是用戶界面線程。
            你也許想知道在你轉到的線程完成之后如何更新用戶界面。要做到這樣,你要使用兩個輔助方法,它們是顯示類(Display)的一部分:asyncExec()syncExec()。(Swing用戶注意:這些方法和Swing工具包類中的invokeLater()invokeAndWait()方法同義。并且,是的,如果你覺得Sun的方法的命名更為清晰,我們贊同。)這些方法按以下方式工作:

          • asyncExec(Runnable)--當你需要更新用戶界面但并不關心具體何時更新時使用。記住,使用此方法意味著后臺線程和用戶界面間的處理不存在任何可保證的關聯。
          • syncExec(Runnable)--當你的背景線程需要先進行用戶界面更新才能繼續處理時使用。注意,在用戶界面更新進行之前,你的背景線程會被阻塞。

            這些方法都采取了實現Runnable接口的類。以下代碼顯示了你一般會如何使用這些方法:

            Display.getDefault().asyncExec(new Runnable()
            {
              public void run()
              {
                button.setText(new Date().toString());
              }
            });

            asyncExec()方法是顯示類的一部分,所以你首先需要取得顯示類的當前實例,這樣做就避免了在你的整個程序中傳遞顯示類的引用。你將一個實現了Runnable接口的類傳遞到asyncExec()方法。通常你創建一個匿名類來進行更新,正如前面的例子所示。

          D.5 構建和運行SWT程序


            你可能想要開始編程了,或者至少也要看一些正確的SWT代碼--很快我們就要這么做。然而,在那之前,讓我們來告訴你如何構建和運行代碼。
            這本書是有關Eclipse的使用的,所以我們首先關注配置Eclipse以使你能進行SWT開發。然后我們來看看需要什么來運行代碼。最后,我們會解釋從命令行運行你的SWT程序時的步驟。
            要配置Eclipse,請按如下步驟進行:

          1. 在[工作空間]視圖中選擇你的項目,選擇右鍵菜單中的[屬性]。
          2. 選擇[Java構建路徑],然后點擊[[庫]]標簽頁。
          3. 選擇[添加外部Jar]。注意,如果你很可能要經常使用SWT,你可能會想要創建一個變量。
          4. 定位到適合你的平臺的swt.jar文件,如圖D.2所示(<eclipse-root>就是Eclipse所在的目錄):
            • Linux GTK --<eclipse-root>/plugins/org.eclipse.swt.gtk_2.1.0/os/linux/x86
            • Linux Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/linux/x86
            • Solaris Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/solaris/sparc
            • AIX Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/aix/ppc
            • HPUX Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/hpux/PA_RISC
            • Photon QNX --<eclipse-root>/plugins/org.eclipse.swt.photon_2.1.0/os/qnx/x86
            • Mac OSX --<eclipse-root>/plugins/org.eclipse.swt.carbon_2.1.0/os/macosx/ppc
          5. 點擊[確定]。



          注意
          對于某些平臺,比如GTK,需要不只一個的JAR來運行SWT(GTK使用文件swt.jar和swt-pi.jar)。在這種情況下,你必須添加所有需要的JAR到classpath中。要這樣做,請對每個JAR文件重復以上步驟。所有的JAR文件都定義在同一個目錄(文件夾)中。

            要運行你的代碼,你需要按以下步驟進行:

          1. 在[工作空間]視圖中,選擇你要運行的包含有main的那個類。
          2. 選擇[運行]->[運行...]。
          3. 在[運行]對話框中,選擇[Java Application]并點擊[新建]。
          4. 選擇[自變量]標簽頁,并在[VM自變量]文本框中點擊鼠標。
          5. 輸入-Djava.library.path=<path>,其中<path>依據你的操作系統而定,是如下之一(如圖D.3所示):
            • Win32 --<eclipse-root>\plugins\org.eclipse.swt.win32_2.1.0\os\win32\x86
            • Linux GTK --<eclipse-root>/plugins/org.eclipse.swt.gtk_2.1.0/os/linux/x86
            • Linux Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/linux/x86
            • Solaris Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/solaris/sparc
            • AIX Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/aix/ppc
            • HPUX Motif --<eclipse-root>/plugins/org.eclipse.swt.motif_2.1.0/os/hpux/PA_RISC
            • Photon QNX --<eclipse-root>/plugins/org.eclipse.swt.photon_2.1.0/os/qnx/x86
            • Mac OSX --<eclipse-root>/plugins/org.eclipse.swt.carbon_2.1.0/os/macosx/ppc
          6. 點擊[應用]然后點擊[調試]。



            你的程序現在運行了。記得中止示例。要這么做,你可以點擊[控制臺]視圖的小方塊。
            從命令行運行你的代碼也差不多:

          1. 確保適合你的平臺的JAR文件在classpath中。
          2. 調用java并帶上-Djava.library.path參數(如前面的步驟所述)以及你的程序名。

          D.6 使用SWT


            我們已經講述了SWT的概念以及如何設置Eclipse以構建及運行示例。現在是看看簡單的SWT示例的時候了。
            我們會帶領你一起瀏覽組成示例的各個類,而不是將這些代碼一下子灌給你。如果你想用Eclipse來照做,確認Eclipse已經按照D.5節描述的步驟設置過了。然后,創建兩個Java類(文件->新建->類):BasicFrameworkMainApp。確認你建有包org.eclipseguide.swt,并是在其中創建它們的。

          D.6.1 BasicFramework類

            讓我們首先來看看BasicFramework。第一個部分定義了該類所在的包,然后導入了示例所需的類:

            package org.eclipseguide.swt;
            
            import org.eclipse.swt.SWT;
            import org.eclipse.swt.events.*;
            import org.eclipse.swt.widgets.*;

            BasicFramework定義為抽象類以確保該類的所有子類都提供dispose()和displayHelpAboutDialog()方法的實現。在這個基礎框架中,這些方法作為提醒來使用,以便你記得要清理資源以及要提供你自己的[關于]對話框。
            代碼的其它部分是你很快就要用到的窗口小部件的聲明:

            public abstract class BasicFramework
            {
              protected Display display;
              protected Shell shell;
              protected Menu menuBar, fileSubMenu, helpSubMenu;
              protected MenuItem fileSubMenuHeader;
              protected MenuItem fileExit, helpSubMenuHeader;
              protected MenuItem helpAbout;
              public abstract void dispose();
              public abstract void displayHelpAboutDialog();

            下面的內部類實現了SelectionListener以便處理選擇事件。它會被連接到[退出]菜單項(很快就定義)。主要做的是關閉窗體,也就是中止消息泵,然后調用dispose()以確保兩個動作銜接在一起:

              class FileExitListener implements SelectionListener
              {
                public void widgetSelected(SelectionEvent event)
                {
                  shell.close();
                  dispose();
                }
                public void widgetDefaultSelected(SelectionEvent event)
                {
                  shell.close(); dispose();
                }
              }

            類似的,下一個內部類處理[幫助]菜單的[關于...]按鈕的選擇事件:

              class HelpAboutListener implements SelectionListener
              {
                public void widgetSelected(SelectionEvent event)
                {
                  displayHelpAboutDialog();       }
                public void widgetDefaultSelected(SelectionEvent event)
                {
                  displayHelpAboutDialog();
                }
              }

          注意
          在這兩個偵聽器類中,widgetSelectedwidgetDefaultSelected這兩個方法處理的事件類型不同。widgetSelected處理用戶用鼠標選擇窗口小部件的事件,例如,點擊一個按鈕。widgetDefaultSelected處理當按鈕具有焦點時,用戶按[空格]鍵或[回車]鍵所產生的事件。

            下面你要開始建立SWT體系結構的層次結構:

              public BasicFramework(String windowTitle)
              {
                display = new Display();
                shell = new Shell(display);
                shell.setText(windowTitle);

            記住,Display窗口小部件是你的程序與操作系統對話的中轉對象。隨即創建Shell并傳遞display給它作為其父部件。該Shell就作為你的頂層窗體,其他所有東西都在其上建立。最后,Shell有一系列的輔助方法:setMinimized()setMaximized()、等等。在這里,你設置了窗口標題。
            在SWT中創建一個全功能菜單欄是一個復雜的過程。設計者不是只提供一些簡單的類諸如菜單欄、菜單、菜單項、子菜單,而是采用了兩個類,并依據所傳遞的樣式來充當不同的角色:

                menuBar = new Menu(shell, SWT.BAR);
                fileSubMenuHeader = new MenuItem(menuBar, SWT.CASCADE);
                fileSubMenuHeader.setText("文件(&F)");

            第一步是創建菜單欄以供其他所有菜單掛載。你可以通過傳遞樣式參數SWT.BAR來實現。然后要創建一個掛載點,基本上就是個供菜單掛載的占位符。最后是設置該占位符顯示在菜單欄上的文字。字母“F”旁的“&”號表明將“F”作為助記符(訪問該菜單的一個鍵盤快捷鍵)。使用時,可以按[Alt]鍵激活菜單然后按[F]鍵來選擇該菜單。然后就可以使用光標鍵來瀏覽菜單了。
            菜單創建工作的下一部分要求你創建在點擊文字[文件]時顯示的菜單。通過指定DROP_DOWN樣式來把它創建為下拉菜單。(另一個可用選項是POP_UP,這將會建立彈出菜單,在右鍵點擊選擇或其它方式中很有用。)然后,把菜單連接到占位符:

                fileSubMenu = new Menu(shell, SWT.DROP_DOWN);
                fileSubMenuHeader.setMenu(fileSubMenu);

            在創建菜單的最后階段里,你要創建菜單的項目。就像過去一樣,你需要指定菜單項的樣式,不過你有更多的選擇--除了創建一個普通按鈕式菜單項,你還可以創建復選項目、單選項目,或者是一個分隔條(用來給你的菜單分段):

                fileExit = new MenuItem(fileSubMenu, SWT.PUSH);
                fileExit.setText("退出(&X)");

            這些和[文件]菜單的寫法一樣:

                helpSubMenuHeader = new MenuItem(menuBar, SWT.CASCADE);
                helpSubMenuHeader.setText("幫助(&H)");
                helpSubMenu = new Menu(shell, SWT.DROP_DOWN);
                helpSubMenuHeader.setMenu(helpSubMenu);
                helpAbout = new MenuItem(helpSubMenu, SWT.PUSH);
                helpAbout.setText("關于(&A)");

            下面就要把偵聽器類連接到菜單項了。從這里開始,當你點擊[文件]菜單的[退出]項或者[幫助]菜單的[關于]項時,這些事件就會被處理:

                fileExit.addSelectionListener(new FileExitListener());
                helpAbout.addSelectionListener(new HelpAboutListener());

            下面一行將菜單欄連接到頂層的shell

                shell.setMenuBar(menuBar);
              }

            以下是BasicFramework類的最后一段代碼。這段很重要,它不僅使頂層窗體(Shell)顯示在屏幕上,還創建了消息泵--這個示例的核心。當你開發獨立運行的程序時,記住,沒有了這一部分,你的程序所能做的將非常有限:

              public void mainLoop(int hSize, int vSize)
              {
                shell.setSize(hSize, vSize);
                shell.setVisible(true);
                shell.open();
                while (!shell.isDisposed())
                {
                  if (!display.readAndDispatch())
                    display.sleep();
                }
              }
            }

          D.6.2 MainApp類

            現在,我們來看看MainApp類,它擴展了BasicFramework類并做了些很有用的工作。像以往一樣,你要將這個類聲明為org.eclipseguide.swt包的成員,然后導入示例需要的所有類:

            package org.eclipseguide.swt;

            import java.util.*;
            import org.eclipse.swt.SWT;
            import org.eclipse.swt.events.*;
            import org.eclipse.swt.layout.FillLayout;
            import org.eclipse.swt.widgets.*;

            要設置一個計時器,你要使用java.util.Timer類而不是使用一個線程。如果你沒用過Java 1.3及以上版本(1.3版是Eclipse運行的最低要求),你可能沒用過這個類。這是一個簡單便捷的類,它提供了一個專用的計時器線程:

            public class MainApp extends BasicFramework
            {
              Timer timer;
              Button button;

            這個按鈕放置在程序的主窗體中并顯示時間。當點擊按鈕時,它會將時間打印到控制臺。
            下面的內部類擴展了抽象類TimerTask。基本上,一個計時器任務就是一個傳遞到計時器的Runnable,它會以指定間隔執行。在run方法中,你要將一個匿名的runnable增加到事件隊列里,以便用當前時間來更新按鈕文本。由于并不關心用戶界面線程什么時候會處理它,所以要用asyncExec方法來加上它:

              private class ClockUpdateTask extends TimerTask
              {
                public void run()
                {
                  Display.getDefault().asyncExec(new Runnable()
                  {
                    public void run()
                    {
                      button.setText(new Date().toString());
                    }
                  });
                }
              }

            這是MainApp類的構造函數。在這里要調用其父類BasicFramework的構造函數并傳遞標題文字:

              public MainApp()
              {
                super("SWT Example Framework");

            每個窗體都可以有一個布局管理器以控制窗口小部件的位置和大小:

                shell.setLayout(new FillLayout(SWT.VERTICAL));

            有5種已定義好的布局:填充布局(FillLayout)堆布局(StackLayout)網格布局(GridLayout)表單布局(FormLayout)以及行布局(RowLayout)。同時還有一個自定義布局(CustomLayout)供你更好的控制窗口小部件的位置。

          提示
          如果要獲得更多關于布局的信息,我們建議你閱讀文章“了解SWT中的布局”(Eclipse站點的文章區載有此文:http://www.eclipse.org/articles/)。

            代碼的下一部分創建了一個普通按鈕并將它加到了shell窗口上。你目前正在使用填充布局,所以無法設置按鈕大小。它只會簡單的擴展到全部可用的空間中:

                button = new Button(shell, SWT.PUSH);

            以下代碼展示了將一個偵聽器連接到一個窗口小部件的另一途徑--將其與一個匿名類連接。對于短小的類來說,應該優先使用匿名類。 除外,建議使用完全類(作為內部類或者友好包):

                button.addSelectionListener(new SelectionListener()
                {
                  public void widgetSelected(SelectionEvent event)
                  {
                    System.out.println( "Button clicked - time is: " + button.getText());
                  }
                  public void widgetDefaultSelected(SelectionEvent event)
                  {
                    System.out.println( "Button pressed with default key - time is: " + button.getText());
                  }
                });

            下面就要創建定時器并安排你的ClockUpdate任務了,它將在0毫秒的延遲后啟動,之后每隔1000毫秒(1秒)調用一次:

                timer = new Timer();
                timer.scheduleAtFixedRate(new ClockUpdateTask(), 0, 1000);

            你不需要告訴計時器開始工作--程序一創建,它就立即運行了。
            以下代碼調用了BasicFramework類的mainloop,在那里會進入事件循環直至shell被關閉。那時,就將會退出程序所運行的JVM:

                this.mainLoop(300, 200);
                System.exit(0);
              }

            這些代碼創建MainApp類并開始整個程序的運行:

              public static void main(String[] args)
              {
                new MainApp();
              }

            現在你就要實現父類的抽象方法了,然而,這些代碼沒有用它們來做任何有用的事情。這種設計是為了讓你能把所有聲明過的資源都放入dispose方法中,以便輕松定位所有需要清理的資源:

              public void dispose()
              {
                System.out.println("Disposing of Resources");
              }
              public void displayHelpAboutDialog()
              {
                System.out.println("Display Help About Dialog");
              }
            }

            我們同樣想象到,你會把創建你的[關于]窗體所需的一切東西放進displayHelpAboutDialog()方法中。

          主站蜘蛛池模板: 陵川县| 武威市| 綦江县| 葵青区| 万年县| 青岛市| 南昌县| 建德市| 临猗县| 张家川| 陆川县| 新安县| 安平县| 祥云县| 抚松县| 类乌齐县| 万载县| 靖州| 莱芜市| 皮山县| 梅州市| 肃北| 海安县| 洪江市| 西乡县| 建昌县| 磐安县| 得荣县| 堆龙德庆县| 新丰县| 师宗县| 舟曲县| 城固县| 得荣县| 新邵县| 通山县| 沈阳市| 岫岩| 申扎县| 平度市| 黔南|