<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    The Spark of Thinking

    Focus on Eclipse Tools.

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      3 隨筆 :: 27 文章 :: 4 評論 :: 0 Trackbacks

    讓你的 swt 程序動起來

    在向使用者提供最差的用戶體驗方面,中國的 IT 企業始終走在時代的最前端。之所以有這樣的感慨其實是來源于往 blog 上貼上一節的內容:我用了一整天的功夫,不斷與 CSDN 各種莫名其妙的出錯提示進行斗爭,最后終于成功的貼了上去。

    其實作為 CSDN blog 一個使用者,我的要求并不高:只要能寫 blog ,能夠正常訪問就可以了。然而就是這么一點基本的要求好像也得不到滿足。

    我不知道大家有沒有這樣的體驗:其實軟件使用者要求的東西都很基本,而現在軟件做得越來越復雜,有相當大一部分是在于軟件開發者把自己的注意力放在了一些附加功能(這些功能可能讓用戶感到驚喜,但是如果沒有它們用戶也不會不滿意)上,而真正用戶的要求卻得不到滿足。所以大家在設計程序的時候,一定要明白,有時候簡單就是一種美,把時間花費到真正有價值的地方去。

    OK ,回到我們的主題上來。在這一節中,我將給大家介紹 swt 的事件模式。在前面我們也提到過,寫一個 swt 程序,無非就是分幾步走。其中比較需要費心的就是布置好用戶界面和處理各種事件。

    添加了事件處理的 Hello,world!

    其實 swt 中處理事件非常簡單,對應于各種事件都有相應的 listener 類,如果一種事件叫做 Xyz ,那么對應的 listener 類就是 XyzListener 。比如對應于鼠標事件的有 MouseListener ,對應于鍵盤事件的就是 KeyListener 。而在每種 widget 中,對于它可以處理的事件都有 addXyzListener 方法,只要把對應的 listener 實例作為參數傳給它就可以了。

    為了更加清楚的說明,我們先來看下面一段程序:

    ?1?public?class?EventDemo?{
    ?2?
    ?3?????private?Shell?_shell;
    ?4?
    ?5?????public?EventDemo()?{
    ?6?????????Display?display?=?new?Display();
    ?7?????????Shell?shell?=?new?Shell(display,SWT.SHELL_TRIM);
    ?8?????????setShell(shell);
    ?9?????????RowLayout?layout=new?RowLayout();
    10?????????shell.setLayout(layout);
    11?????????shell.setText("Event?demo");
    12?????????
    13?????????Button?button=new?Button(shell,SWT.PUSH?|?SWT.CENTER);
    14?????????button.setText("Click?me!");
    15?
    16?????????button.addSelectionListener(new?SelectionListener(){
    17?
    18?????????????public?void?widgetSelected(SelectionEvent?event)?{
    19?????????????????handleSelectionEvent();
    20?????????????}
    21?
    22?????????????public?void?widgetDefaultSelected(SelectionEvent?event)?{
    23?????????????}?????
    24?????????});
    25?????????shell.setBounds(200,300,100,100);
    26?????????shell.open();
    27?
    28?????????while?(!shell.isDisposed())?{
    29?????????????if?(!display.readAndDispatch())?{
    30?????????????????display.sleep();
    31?????????????}
    32?????????}
    33?????????display.dispose();????
    34?????????
    35?????}
    36?
    37?????protected?void?handleSelectionEvent()?{
    38?????????MessageBox?dialog=new?MessageBox(getShell(),SWT.OK|SWT.ICON_INFORMATION);
    39?????????dialog.setText("Hello");
    40?????????dialog.setMessage("Hello,world!");
    41?????????dialog.open();
    42?????}
    43?
    44?????/**
    45??????*?@param?args
    46??????*/
    47?????public?static?void?main(String[]?args)?{
    48?
    49?????????EventDemo?eventdemo=new?EventDemo();
    50?????}
    51?
    52?????/**
    53??????*?@return?Returns?the?_shell.
    54??????*/
    55?????public?Shell?getShell()?{
    56?????????return?_shell;
    57?????}
    58?
    59?????/**
    60??????*?@param?_shell?The?_shell?to?set.
    61??????*/
    62?????public?void?setShell(Shell?shell)?{
    63?????????this._shell?=shell;
    64?????}
    65?}
    66?

    代碼段 6

    你可以看到在這段程序中,我們只創建了一個 Button ,隨后調用了它的 addSelectionListener() 方法,在這個新創建的 Listener ,我們只為 widgetSelected 方法添加了代碼,并在其中創建了一個對話框。實際運行效果如下圖,其中那個標有 Hello,world 的對話框是按了按鈕以后出現的:

    6

    如果總結一下,我們可以得出處理事件的幾個步驟:

    1. ????? 針對你所處理的事件,找出合適的 XyzListener 接口

    2. ????? 編寫一個新的類,這個類實現了 XyzListener 接口

    3. ????? 在你所感興趣的事件中編寫處理代碼,而對于那些你不感興趣的方法可以讓它們保持空白(就像實例中的 widgetDefaultSelected() 方法)一樣

    讓事件處理更加簡單:使 用適配器( adapter

    有時候我們可能會感覺這樣仍然不夠簡單,比如我只對 SelectionListener 中的 widgetSelected() 方法感興趣,但是為了能夠通過編譯器的編譯,我卻不得不寫一個空白的 widgetDefaultSelected() 方法(因為 SelectionListener 是一個接口,你必須實現它所有的方法)。

    幸運的是, swt 幫我們解決了這個問題,途徑就是使用 adapter 。在 swt 中,對應于一個 XyzListener 都有一個 XyzAdapter adapter 都是抽象類并且實現了對應的 listener 接口,它為對應 listener 接口中的每個方法都定義了一個默認實現(基本上就是什么都不做),我們在使用時候只需要 override 掉自己感興趣的方法就可以了。

    結合上一小節中的代碼,如果使用 SelectionAdapter 代替 SelectionListener 的話,我們的代碼就可以這樣寫:

    button.addSelectionListener( new ?SelectionAdapter(){
    ????????????
    public ? void ?widgetSelected(SelectionEvent? event )?{
    ????????????????handleSelectionEvent();
    ????????????}
    ????????});

    這樣是不是很方便呢?

    EventObject 事件處理的附加信息

    在處理各種事件時,我們需要一些附加信息,而 EventObject 給我們提供了這些信息。

    我們先來看下面這個簡單的小程序,在這段程序中,我們創建了兩個文本框,當在第一個文本框輸入時,第二個文本框中顯示輸入的字符。

    ?1?public?class?EventDemo2?{
    ?2?
    ?3?????Text?logText;
    ?4?????
    ?5?????public?EventDemo2()?{
    ?6?????????Display?display?=?new?Display();
    ?7?????????Shell?shell?=?new?Shell(display,SWT.SHELL_TRIM);
    ?8?????????
    ?9?????????GridLayout?layout=new?GridLayout();
    10?????????layout.numColumns=2;
    11?????????shell.setLayout(layout);
    12?????????shell.setText("Event?demo");
    13?????????
    14?????????Label?label1=new?Label(shell,SWT.RIGHT);
    15?????????label1.setText("text1:");
    16?????????Text?text1=new?Text(shell,SWT.NONE);
    17?????????
    18?????????text1.addKeyListener(new?KeyAdapter(){
    19?????????????public?void?keyPressed(KeyEvent?e)?{
    20?????????????????Text?t=getLogText();
    21?????????????????String?s=t.getText();
    22?????????????????t.setText(String.valueOf(e.character));
    23?????????????}?
    24?????????}
    25?????????);
    26?????????
    27?????????Label?label2=new?Label(shell,SWT.RIGHT);
    28?????????label2.setText("text2:");
    29?????????Text?text2=new?Text(shell,SWT.NONE);
    30?????????text2.setEditable(false);
    31?????????text2.setBackground(new?Color(display,255,255,255));
    32?????????setLogText(text2);
    33?????????
    34?????????shell.pack();
    35?????????shell.open();
    36?
    37?????????while?(!shell.isDisposed())?{
    38?????????????if?(!display.readAndDispatch())?{
    39?????????????????display.sleep();
    40?????????????}
    41?????????}
    42?????????display.dispose();???????????
    43?????}
    44?????/**
    45??????*?@param?args
    46??????*/
    47?????public?static?void?main(String[]?args)?{
    48?????????EventDemo2?demo2=new?EventDemo2();
    49?????}
    50?????/**
    51??????*?@return?Returns?the?logText.
    52??????*/
    53?????public?Text?getLogText()?{
    54?????????return?logText;
    55?????}
    56?????/**
    57??????*?@param?logText?The?logText?to?set.
    58??????*/
    59?????public?void?setLogText(Text?logText)?{
    60?????????this.logText?=?logText;
    61?????}
    62?}
    63?

    代碼段 7

    你可能沒有興趣仔細研究這么長的代碼,那么讓我們只關注這一小段代碼:

    ?text1.addKeyListener( new ?KeyAdapter(){
    ????????????
    public ? void ?keyPressed(KeyEvent?e)?{
    ????????????????Text?t
    = getLogText();
    ????????????????String?s
    = t.getText();
    ????????????????t.setText(String.valueOf(e.character));
    ????????????}?
    ????????}
    ????????);

    在這段代碼中,我們使用了 KeyAdapter 來處理鍵盤事件,而 keyPressed 會在有鍵按下時候被調用,我們在函數中使用了 KeyEvent 類型的參數 e ,并且通過 e.character 得到了按下鍵對應的字符。

    各種 EventObject (例如上面示例中的 KeyEvent )在事件處理函數中作為參數出現,它們可能有不同的屬性和方法,利用這些特性我們可以做很多有意思的事情。

    我們下面只簡單介紹幾種 EventObject ,它們分別是對應于窗口事件( ShellListener ShellAdapter )的 ShellEvent ,對應于鍵盤事件 (KeyListener KeyAdapter) KeyEvent 和對應于鼠標事件( MouseListener MouseAdapter )的 MouseEvent 。希望可以起到窺一斑而見全豹的作用。

    幾種 EventObject 簡介

    ShellEvent

    如果你打開 ShellEvent API ,你會很驚訝的發現它只有一個布爾型的屬性,就是 doit 。這個莫名其妙的屬性是用來做什么的呢?

    我們知道, Shell 對應的就是程序的窗口,在 ShellListener 中定義的幾種事件包括窗口激活時候的 shellActivated ,窗口即將被關閉時候的 shellClosed 等等。 ShellEvent 中唯一的屬性 doit ,就是用來設定是否這些動作將有效的。

    再說得具體一些,比如 Windows 下通常我們會通過點擊窗口右上角的關閉按鈕來關閉窗口,這個時候就會對 shellClosed 進行調用,如果我們在 shellClosed (ShellEvent e) 方法中把 ShellEvent 對象 e doit 屬性置為了 false ,那么這次動作就無效,窗口不會被關閉。

    在有些其他的 EventObject 中也有 doit 屬性,它們的作用都是類似的。比如 KeyEvent 就有這樣的一個屬性。如果你在 keyPressed 方法中把它置為了 false ,就等于你按鍵盤(對于對應的 widget ,也就是 receiver 來講)沒有用。

    KeyEvent

    其實在前面我們或多或少的已經介紹了一些 KeyEvent 的知識。 KeyEvent 包含四個屬性: character doit keyCode stateMask

    其中 character 我們在前面的示例中使用過,它其實就是按鍵對應字符,而 doit ShellEvent 中的 doit 含義是相同的。

    keyCode 是我們稱為鍵碼的東西,什么是鍵碼呢?如果你打開 org.eclipse.swt.SWT API 文檔,你會發現里面有很多都和鍵盤有關的整型常量,比如 SWT.F1 SWT.F4 SWT.ESC SWT.KEYPAD_3 之類,這就是他們的鍵碼。

    stateMask 則是用來檢測 Alt Shift Ctrl 這些鍵有沒有同時被按下。

    stateMask 與這些鍵的鍵碼進行位與運算,如果得到的結果不是 0 就說明這些鍵被按下了,比如如果 stateMake & SWT.ALT 不為零,我們就可以認為 Alt 鍵被按下了。

    MouseEvent

    MouseEvent 對應于的是鼠標事件。它同樣包含四個屬性: button stateMask x y

    button 就是說明按下的是哪個鍵,比如對于普通鼠標來說, 1 是左鍵, 2 是右鍵等等

    stateMask 卻是用來反映鍵盤的狀態的,這和 KeyEvent 中的 stateMask 含義是相同的。

    x y 指的是相對于部件的橫坐標和縱坐標。

    你可能會覺得有點疑問,光是這么一點屬性就能處理鼠標事件了么?如果我有一個滾輪鼠標,那應該用什么事件處理滾輪的動作呢?答案是:目前可能還無法利用事件模式處理,關于這一點可以參照一下這個 url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=58656

    關于 EventObject 我就只介紹到這里,這當然很不夠,但是我強烈建議大家在實際應用中多查閱 eclipse swt 的相關文檔。因為畢竟精力有限,我的目的是讓大家通過這篇文章能夠找到一個正確獲取知識的方向,而不是把這些知識很詳細的介紹給大家。

    Untyped Events

    我們在這里提到了 untyped events ,那肯定就有 typed event typed untyped 本身并不是說事件有什么不一樣,而是說事件處理是使用了特定的 Listener 還是沒有。我們前面提到的所有事件處理都是 typed 類型,因為它們都使用了特定 Listener

    所謂的 untyped events 你可以理解為一個事件的大雜燴。和 untyped event 相聯系的兩個類是 Listener Event 。在這里我想請大家注意一下,這兩個類不是在 org.eclipse.swt.events 中,而是在 org.eclipse.swt.widgets 中。

    Listener 只有一個方法 handleEvent ,這個方法里你可以處理任何事件。而如果你打開 Event 看一下,就能看到我們剛剛在前一小節中介紹過的那些 XxxEvent 中的屬性在這里應有盡有。所以它可以起到替代它們的作用,當然如果是一個窗口被關閉的事件,相信你用 keyCode 屬性意義不大。

    讓我們看一下下面一段代碼

    ?1?Shell?shell?=?new?Shell?();
    ?2????Listener?listener?=?new?Listener?()?{
    ?3???????public?void?handleEvent?(Event?e)?{
    ?4??????????switch?(e.type)?{
    ?5?????????????case?SWT.Resize:
    ?6????????????????System.out.println?("Resize?received");
    ?7????????????????break;
    ?8?????????????case?SWT.Paint:
    ?9????????????????System.out.println?("Paint?received");
    10????????????????break;
    11?????????????default:
    12????????????????System.out.println?("Unknown?event?received");
    13??????????}
    14???????}
    15????};
    16????shell.addListener?(SWT.Resize,?listener);
    17????shell.addListener?(SWT.Paint,?listener);
    18?

    代碼段 8

    由此我們大體上可以體會到 untyped events 的處理方式。

    小結

    關于事件處理,我就向大家介紹這么多。到現在為止,我們已經基本上可以寫一些簡單的 swt 用戶交互程序了。然而這還遠遠不夠,畢竟人們總是希望有更華麗(或者說:豐富)的界面,讓用戶能夠獲得更好的體驗。在下一節中,我計劃和大家討論一些這樣的部件。

    另外可能你覺得有些疑惑,為什么寫了這么多內容,都是關于 swt 的呢? Jface 的內容呢?我的計劃是在大部分 swt 有關的內容介紹完了以后再向大家介紹 Jface 。事實上,即使不用 Jface ,你也完全可以用 swt 構筑起一個非常完美的程序來。

    最后,給自己做一個小廣告,因為 CSDN blog 功能實在太令人失望了,所以我希望在近期內可以把 blog 遷移到 blogjava.net ,具體地址是: http://m.tkk7.com/jayliu ,歡迎大家提出寶貴意見。



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=374082

    posted on 2006-07-20 17:59 The Spark of Thinking 閱讀(262) 評論(0)  編輯  收藏 所屬分類: SWT/JFace
    主站蜘蛛池模板: 青青草a免费线观a| 人人狠狠综合久久亚洲婷婷| 免费无码成人AV在线播放不卡| 亚洲欧洲AV无码专区| 亚洲第一香蕉视频| 亚洲国产精品久久久天堂| 亚洲精品无码av天堂| 国产极品粉嫩泬免费观看 | 日本免费一区尤物| 亚洲免费观看网站| 99精品免费观看| 光棍天堂免费手机观看在线观看| 另类图片亚洲校园小说区| 亚洲色大成网站www永久男同 | 曰批全过程免费视频在线观看| 麻豆成人久久精品二区三区免费| 怡红院免费的全部视频| 国产精品成人免费观看| 日本高清不卡中文字幕免费| 国产亚洲情侣久久精品| 色窝窝亚洲av网| 亚洲AV无码成人网站在线观看| 一本色道久久综合亚洲精品蜜桃冫| 中文字幕亚洲第一在线| 亚洲成色在线影院| 亚洲欧洲日产国码久在线观看 | 91视频免费观看| 久久久久久久久久免免费精品 | 国产男女性潮高清免费网站 | 一级人做人a爰免费视频| 亚洲AV永久无码精品放毛片| 亚洲天然素人无码专区| 亚洲国产成人久久一区二区三区| 亚洲欧美成人一区二区三区| 亚洲a∨国产av综合av下载 | 四虎免费影院4hu永久免费| 国产jizzjizz视频全部免费| 亚洲国产成人精品久久久国产成人一区二区三区综 | 一级视频免费观看| 久久国产免费直播| 久久国产免费一区|