到目前為止,我們已使用了action(),現有另一種方法handleEvent()可對每一事件進行嘗試。當一個事件發生時,它總是針對單獨事件或發生在單獨的事件對象上。該對象的handleEvent()方法是自動調用的,並且是被handleEvent()創建並傳遞到handleEvent()裡。默認的handleEvent()(handleEvent()定義在組件裡,基礎類的所有控件都在AWT裡)將像我們以前一樣調用action()或其它同樣的方法去指明鼠標的活動、鍵盤活動或者指明移動的焦點。我們將會在本章的後面部分看到。
如果其它的方法-特別是action()-不能滿足我們的需要怎麼辦呢?至於列表框,例如,如果我想捕捉鼠標單擊,但action()只響應雙擊怎麼辦呢?這個解答是過載handleEvent(),畢竟它是從程序片中得到的,因此可以過載任何非確定的方法。當我們為程序片過載handleEvent()時,我們會得到所有的事件在它們發送出去之前,所以我們不能假設“這裡有我的按鈕可做的事件,所以我們可以假設按鈕被按下了”從它被action()設為真值。在handleEvent()中按鈕擁有焦點且某人對它進行分配都是可能的。不論它合理與否,我們可測試這些事件並遵照handleEvent()來進行操作。
為了修改列表樣本,使它會響應鼠標的單擊,在action()中按鈕測試將被過載,但代碼會處理的列表將像下面的例子被移進handleEvent()中去:
//: List2.java // Using lists with handleEvent() import java.awt.*; import java.applet.*; public class List2 extends Applet { String[] flavors = { "Chocolate", "Strawberry", "Vanilla Fudge Swirl", "Mint Chip", "Mocha Almond Fudge", "Rum Raisin", "Praline Cream", "Mud Pie" }; // Show 6 items, allow multiple selection: List lst = new List(6, true); TextArea t = new TextArea(flavors.length, 30); Button b = new Button("test"); int count = 0; public void init() { t.setEditable(false); for(int i = 0; i < 4; i++) lst.addItem(flavors[count++]); add(t); add(lst); add(b); } public boolean handleEvent(Event evt) { if(evt.id == Event.LIST_SELECT || evt.id == Event.LIST_DESELECT) { if(evt.target.equals(lst)) { t.setText(""); String[] items = lst.getSelectedItems(); for(int i = 0; i < items.length; i++) t.appendText(items[i] + "\n"); } else return super.handleEvent(evt); } else return super.handleEvent(evt); return true; } public boolean action(Event evt, Object arg) { if(evt.target.equals(b)) { if(count < flavors.length) lst.addItem(flavors[count++], 0); } else return super.action(evt, arg); return true; } } ///:~
這個例子同前面的例子相同除了增加了handleEvent()外簡直一模一樣。在程序中做了試驗來驗證是否列表框的選擇和非選擇存在。現在請記住,handleEvent()被程序片所過載,所以它能在窗體中任何存在,並且被其它的列表當成事件來處理。因此我們同樣必須通過試驗來觀察目標。(雖然在這個例子中,程序片中只有一個列表框所以我們能假設所有的列表框事件必須服務於列表框。這是一個不好的習慣,一旦其它的列表框加入,它就會變成程序中的一個缺陷。)如果列表框匹配一個我們感興趣的列表框,像前面的一樣的代碼將按上面的策略來運行。注意handleEvent()的窗體與action()的相同:如果我們處理一個單獨的事件,將返回真值,但如果我們對其它的一些事件不感興趣,通過handleEvent()我們必須返回super.handleEvent()值。這便是程序的核心,如果我們不那樣做,其它的任何一個事件處理代碼也不會被調用。例如,試注解在上面的代碼中返回super.handleEvent(evt)的值。我們將發現action()沒有被調用,當然那不是我們想得到的。對action()和handlEvent()而言,最重要的是跟著上面例子中的格式,並且當我們自己不處理事件時一直返回基礎類的方法版本信息。(在例子中我們將返回真值)。(幸運的是,這些類型的錯誤的僅屬於Java 1.0版,在本章後面將看到的新設計的Java 1.1消除了這些類型的錯誤。)
在windows裡,如果我們按下shift鍵,列表框自動允許我們做多個選擇。這非常的棒,因為它允許用戶做單個或多個的選擇而不是編程期間固定的。我們可能會認為我們變得更加的精明,並且當一個鼠標單擊被evt.shiftdown()產生時如果shift鍵是按下的將執行我們自己的試驗程序。AWT的設計妨礙了我們-我們不得不去了解哪個項目被鼠標點擊時是否按下了shift鍵,所以我們能取消其余部分所有的選擇並且只選擇那一個。不管怎樣,我們是不可能在Java 1.0版中做出來的。(Java 1.1將所有的鼠標、鍵盤、焦點事件傳送到列表中,所以我們能夠完成它。)