Download presentation
Presentation is loading. Please wait.
1
事件處理
2
內 容 大 綱 何謂事件 利用事件來源處理事件 委託傾聽者處理事件 轉接類別事件處理 內層類別事件處理
3
何謂事件 (1/4) 在Java語言中,一個物件狀態的改變就可以引發一個事件(event)。
例如,當AWT (Abstract Window Toolkit)圖形使用者介面中的按鈕(Button)元件物件被按下時,會因為按鈕元件狀態的改變而引發一個事件。 又例如,當AWT圖形使用者介面中的捲軸(Scrollbar)元件物件被拉動時也會一個事件。 通常,一個事件驅動程式不會有任何動作直到一個事件的發生驅動了一個事先規劃好的方法(程序)為止。
4
何謂事件 (2/4) 在Java語言中,事件被視為物件,當事件發生後,系統會建構出與事件相對應的物件。
例如,當使用者按下一個按鈕元件,系統將新建構出一個屬於ActionEvent類別的物件,物件中儲存著該事件的細節,例如事件於何時發生、於何地發生等。 下表所列是java.awt.event類別庫中定義的事件相關類別的說明,說明中包括事件的使用元件(即可以產生這些事件的元件)及事件產生時機。
5
事件 使用元件 發生時機 ActionEvent Button 當按鈕按下 List 當選項被選擇 MenuItem 當功能表項目被選擇 TextField 當「Enter」鍵被按下時 AdjustmentEvent Scrollbar 當捲軸調整動作產生時 ComponentEvent Component及其所有衍生類別 當元件移動、改變大小或改變可見度等 ContainerEvent Container及其所有衍生類別 當元件加入容器或自容器中移除 FocusEvent 當元件取得(gain)或失去(lost)鍵盤輸入焦點(input focus)
6
ItemEvent Checkbox 當Checkbox元件選項被選擇或取消選擇時 CheckboxMenuItem 當CheckboxMenuItem元件選項被選擇或取消選擇時 Choice 當Choice元件選項被選擇或取消選擇時 List 當List元件選項被選擇或取消選擇時 KeyEvent Component及其所有衍生類別 當鍵盤有按鍵動作產生時 MouseEvent 當滑鼠左鍵被按下(pressed)、放開(released)、點選(clicked),滑鼠指標(cursor)進入或離開某個元件,滑鼠指標移動或拖曳(drag) TextEvent TextField 文字內容更動時 TextArea WindowEvent Window及其所有衍生類別 所有窗框改變狀態時,如開啟、關閉、啟動(activate)或不啟動(deactive)或圖像化(iconify)或解圖像化(deiconify)
7
何謂事件 (3/4) 當事件發生時,我們有三種方式來處理這個事件: 1. 忽略事件 2. 利用事件來源(event source)處理事件
3. 委任(delegate) 傾聽者(listener)處理事件 所謂忽略事件就是根本不對事件加以處理,例如,我們在第九章中所提到的所有圖形使用者介面元件都是忽略事件的例子。
8
何謂事件 (4/4) 在這些例子中的每一個圖形使用者介面元件都可以讓使用者隨意操作,例如,按下按鈕、拉動捲軸、在選單中做選擇等。
這些動作雖然都會引起事件發生,但是因為程式忽略了事件,所以並不會引發任何程式碼的執行。
9
利用事件來源處理事件 (1/5) 所謂事件來源(event source)就是產生事件的物件,因此,利用事件來源處理事件就是由產生事件的物件本身來處理這個事件。 一個能夠處理本身所產生事件的物件稱為自我完備(self-contained)物件(當然,若物件為圖形使用者介面元件則可稱為自我完備元件),要設計一個自我完備的物件(元件)需要執行以下兩個動作: 1. 呼叫enableEvents方法利用事件標示(event mask)以啟動(enable)事件 2. 編寫與被標示事件相對應的事件處理(event handling)方法以處理事件
10
利用事件來源處理事件 (2/5) 方法enableEvents必須傳入一個參數以啟動(enable)事件,傳入enableEvents方法的參數稱為事件標示(event mask),而一個事件被啟動之後表示系統將隨時監控此事件的發生而不再只是忽略事件。 每一個事件都有對應的事件處理(event handling)方法,於事件發生時被呼叫執行,以便對事件進行適當的處置。
11
利用事件來源處理事件 (3/5) 下表中所列是java.awt類別庫的AWTEvent類別中所定義的11種不同事件標示,此11個事件標示涵蓋上表中圖形使用者介面元件所能產生的10種事件。 例如,AWTEvent.ACTION_EVENT_MASK事件標示對應於ActionEvent事件的啟動,而對應的事件處理方法為processActionEventm,餘類推。 請注意,AWTEvent.MOUSE_EVENT_MASK與AWTEventMOUSE_MOTION_EVENT_MASK 都對應於MouseEvent事件的啟動,並且都是對應processMouseEvent事件處理方法。
12
事件標示(event mask) 對應之事件處理方法 AWTEvent.ACTION_EVENT_MASK processActionEvent() AWTEvent.ADJUSTMENT_EVENT_MASK processAdjustmentEvent() AWTEvent.COMPONENT_EVENT_MASK processComponentEvent() AWTEvent.CONTAINER_EVENT_MASK processContainerEvent() AWTEvent.FOCUS_EVENT_MASK processFocusEvent() AWTEvent.ITEM_EVENT_MASK ProcessItemEvent() AWTEvent.KEY_EVENT_MASK processKeyEvent() AWTEvent.MOUSE_EVENT_MASK processMouseEvent() AWTEvent.MOUSE_MOTION_EVENT_MASK processMouseMotionEvent() AWTEvent.TEXT_EVENT_MASK processTextEvent() AWTEvent.WINDOW_EVENT_MASK processWindowEvent()
13
利用事件來源處理事件 (4/5) 我們使用以下的範例來說明利用事件來源處理事件(即自我完備元件)的做法:
1: //檔名:自我完備按鈕測試.java 2: //說明:事件來源處理事件(自我完備元件)測試 3: import java.applet.Applet; //引入Applet類別 4: import java.awt.Button; //引入Button類別 5: import java.awt.AWTEvent; 6: import java.awt.event.ActionEvent; 7: public class 自我完備按鈕測試 extends Applet { 8: public void init() { 9: add( new 自我完備按鈕("請趕快按我!!") ); 10: } 11: } //類別:自我完備按鈕測試 定義區塊結束
14
利用事件來源處理事件 (5/5) 12: 13: class 自我完備按鈕 extends Button {
12: 13: class 自我完備按鈕 extends Button { 14: int 按鈕被按次數=0; 15: public 自我完備按鈕(String 標記) { 16: super(標記); 17: enableEvents(AWTEvent.ACTION_EVENT_MASK); 18: } 19: 20: public void processActionEvent(ActionEvent 事件) { 21: super.processActionEvent(事件); 22: 按鈕被按次數++; 23: setLabel("按鈕被按下"+按鈕被按次數+"次"); 24: } 25: } //類別:自我完備按鈕 定義區塊結束 程式執行結果
15
委託傾聽者處理事件 (1/11) 事件發生之後不由引發事件發生的事件來源(event source)物件自行處理物件,而是由其他的物件來處理事件,稱為事件委託(event deligation),接受委託而處理事件的物件稱為傾聽者(listener)。 委託(deligate)傾聽者(listener)處理事件的模式如下所示:
16
委託傾聽者處理事件 (2/11) 事件委託需要完成以下的步驟:
以介面實作(interface implementation)方式編寫完成事件傾聽者 至事件來源物件登記事件傾聽者 Java語言有許多介面可供傾聽者實作,每一個介面都對應至圖形使用者介面元件所能產生的10種事件中的一種,我們將這些介面稱為傾聽者介面。 例如,傾聽者介面ActionListener對應ActionEvent事件,傾聽者介面AdjustmentListener對應AdjustmentEvent事件,餘類推…。
17
委託傾聽者處理事件 (3/11) 每一個傾聽者介面中都包含許多等待實作的方法,下表列出每一個傾聽者介面及其中包含的等待實作方法。
例如,傾聽者介面ActionListener中包含等待實作方法actionPerformed(ActionEvent 事件);傾聽者介面AdjustmentListener中包含等待實作方法adjstmentValueChanged(AdjustmentEvent 事件)。
18
傾聽者介面 介面中等待實作的方法 傾聽者登記方法 ActionListener ActionPerformed(ActionEvent 事件) addActionListener() AdjustmentListener AdjstmentValueChanged(AdjustmentEvent 事件) addAdjustmentListener() ComponentListener componentHidden(componentEvent 事件) componentMoved(componentEvent 事件) componentResized(componentEvent 事件) componentShow(componentEvent 事件) addComponentListener() ContainerListener componentAdded(ContainerEvent 事件) componentRemoved(ContainerEvent 事件) addContainerListener() FocusListener focusGained(FocusEvent 事件) focusLost(FocusEvent 事件) addFocusListener() ItemListener itemStateChanged(itemEvent 事件) additemListener() KeyListener keyPressed(KeyEvent 事件) keyReleased(KeyEvent 事件) keyTyped(KeyEvent 事件) addKeyListener()
19
MouseListener mouseClicked(MouseEvent 事件) mouseEnetered(MouseEvent 事件) mouseExited(MouseEvent 事件) mousePressed(MouseEvent 事件) mouseReleased(MouseEvent 事件) addMouseListener() MouseMotionListener mouseDragged(MouseEvent 事件) mouseMoved(MouseEvent 事件) addMouseMotionListener() TextListener textValueChanged(TextEvent 事件) addTextListener() WindowListener windowActivated(WindowEvent 事件) windowClosed(WindowEvent 事件) windowClosing(WindowEvent 事件) windowDeactivated(WindowEvent 事件) windowDeiconified(WindowEvent 事件) windowIconified(WindowEvent 事件) windowOpened(WindowEvent 事件) addWindowListener()
20
委託傾聽者處理事件 (4/11) 當我們編寫完傾聽者介面中等待實作的方法後,就完成傾聽者的定義了。
傾聽者的定義完成之後,我們還必須至事件來源物件登記事件傾聽者。 每一個傾聽者介面都有一個對應的傾聽者登記方法,上表中也列出每一個傾聽者介面及其對應的傾聽者登記方法。例如,傾聽者介面ActionListener,傾聽者介面AdjustmentListener對應addAdjustmentListener傾聽者登記方法,餘類推…。
21
委託傾聽者處理事件 (5/11) 我們利用以下的範例來說明如何達成委託傾聽者處理事件: 1: //檔名:事件委託按鈕測試.java
2: //說明:測試「事件委託」處理模式 3: import java.applet.Applet; //引入Applet類別 4: import java.awt.Button; //引入Button類別 5: import java.awt.event.ActionEvent; 6: import java.awt.event.ActionListener;
22
委託傾聽者處理事件 (6/11) 7: public class事件委託按鈕測試 extends Applet {
8: Button 按鈕 = new Button("請趕快按我!!"); 9: public void init() { 10: add(按鈕); 11: ActionListener 傾聽者物件= new 傾聽者(); 12: 按鈕.addActionListener(傾聽者物件); 13: //上2行可以使用 按鈕.addActionListener(new 傾 聽者()); 取代之 14: } 15: } //類別:事件委託按鈕測試 定義區塊結束
23
委託傾聽者處理事件 (7/11) 16: class 傾聽者 implements ActionListener {
17: int 按鈕被按次數=0; 18: public void actionPerformed (ActionEvent 事件) { 19: 按鈕被按次數++; 20: Object 物件=事件.getSource(); 21: Button 按鈕物件=(Button)物件; 22: 按鈕物件.setLabel(“按鈕被按下”+按鈕被按次數+“次 "); 23: } //方法:actionPerformed() 定義區塊結束 24: } //類別:傾聽者 定義區塊結束 程式執行結果
24
委託傾聽者處理事件 (8/11) 在自我完備按鈕測試中我們直接使用setLabel方法來改變按鈕的標記。
這是因為自我完備按紐就是按鈕動作事件的來源,而在“按鈕動作事件委託測試”程式中,由於事件來源與事件處理者並不是相同的物件,因此我們為了更改事件來源按鈕的標記,我們必須在事件處理者中先取得事件來源物件才可以更改到正確的按紐元件上的標記,我們使用事件.getSource()方法傳回事件的來源物件,再使用(Button)物件將物件轉換為始於Button類別的物件。
25
委託傾聽者處理事件 (9/11) 我們可以將物件的事件委託給物件本身處理,稱為自我傾聽者(self-listener),如“自我傾聽按鈕測試.java”所作的一般,通常這種方式比較不會引起錯誤。 由以上的“按鈕事動作件委託測試.java”,我們可以知道事件委託必須先實作(implements)動作事件傾聽者(ActionListener)介面中的actionPerformed方法,並在事件來源元件中使用addActionListener方法將傾聽者登記至事件來源元件。
26
委託傾聽者處理事件 (10/11) 1: //檔名:自我傾聽按鈕測試.java 2: //說明:測試「自我傾聽」處理模式
2: //說明:測試「自我傾聽」處理模式 3: import java.applet.Applet; //引入Applet類別 4: import java.awt.Button; //引入Button類別 5: import java.awt.event.ActionEvent; 6: import java.awt.event.ActionListener; 7: public class 自我傾聽按鈕測試 extends Applet { 8: 自我傾聽按鈕 按鈕物件 = new 自我傾聽按鈕("請趕快按我!!"); 9: public void init() { 10: add(按鈕物件); 11: 按鈕物件.addActionListener(按鈕物件); 12: } 13: } //類別: 自我傾聽按鈕測試 定義區塊結束
27
委託傾聽者處理事件 (11/11) 14: 15: class 自我傾聽按鈕 extends Button implements
14: 15: class 自我傾聽按鈕 extends Button implements ActionListener { 16: int 按鈕被按次數=0; 17: 自我傾聽按鈕(String 標記) { 18: super(標記); 19: } 20: public void actionPerformed (ActionEvent 事件) { 21: 按鈕被按次數++; 22: setLabel("按鈕被按下"+按鈕被按次數+"次"); 23: } 24: } //類別:自我傾聽按鈕 定義區塊結束 程式執行結果
28
轉接類別事件處理 (1/12) 由表10-3中可知,大部分的傾聽者介面都具有多個等待實作的方法。
例如,WindowListener介面包含windowActivated( WindowEvent 事件) 、windowClosed( WindowEvent 事件) 、windowClosing( WindowEvent 事件) 、windowDeactivated( WindowEvent 事件) 、windowDeiconified( WindowEvent 事件) 、windowIconified( WindowEvent 事件) 及windowOpened( WindowEvent 事件)等7個等待實作的方法。
29
轉接類別事件處理 (2/12) 我們必須將每一個等待實作的方法定義完畢之後才可以完成傾聽者介面的實作。
即使有一些方法並不會被用到,我們仍然要編寫對應這個方法的「空的」(不具任何程式碼)定義,這使得傾聽者介面的實作變得有點繁瑣。 為了簡化傾聽者介面的實作,Java語言提供了轉接類別(adapter)。 轉接類別實作一個對應的傾聽者介面並為其中每個等待實作的方法提供一個「空的」,不具任何程式碼的定義,我們不需要再執行繁瑣的填入「空的」方法定義步驟,而只需要挑出使用到的方法並將之加以定義就可以了。
30
轉接類別事件處理 (3/12) 下表中列出所有的轉接類別及其對應的傾聽者介面: 轉接類別 對應的傾聽者介面 ComponentAdapter
ComponentListener ContainerAdapter ContainerListener FocusAdapter FocusListener KeyAdapter KeyListener MouseAdapter MouseListener MouseMotionAdapter MouseMotionListener WindowAdapter WindowsListener
31
轉接類別事件處理 (4/12) 以下我們以關閉窗框為例,來說明使用傾聽者介面與轉接類別的不同點。我們先看使用傾聽者介面的範例。
1: //檔名:窗框關閉使用傾聽者介面測試.java 2: //說明:測試傾聽者介面用法 3: import java.applet.Applet; //引入Applet類別 4: import java.awt.Frame; //引入Button類別 5: import java.awt.event.WindowEvent; 6: import java.awt.event.WindowListener;
32
轉接類別事件處理 (5/12) 7: public class 窗框關閉使用傾聽者介面測試 extends Applet {
8: Frame 窗框; 9: public void init() { 10: 窗框 = new Frame("測試窗框"); 11: 窗框.setSize(200,200); 12: 窗框.setVisible(true); 13: 窗框.addWindowListener(new 傾聽者() ); 14: } 15: } //類別:窗框關閉使用傾聽者介面測試 定義區塊結束 16:
33
轉接類別事件處理 (6/12) 17: class 傾聽者 implements WindowListener {
18: public void windowClosing (WindowEvent 事件) { 19: Object 物件=事件.getSource(); 20: Frame 窗框物件=(Frame)物件; 21: 窗框物件.dispose(); 22: } //方法:windowClosing定義區塊結束
34
轉接類別事件處理 (7/12) 23: public void windowActivated(WindowEvent 事件) { } //「空的」方 法定義 24: public void windowClosed(WindowEvent 事件) { } //「空的」方法 定義 25: public void windowDeactivated(WindowEvent 事件) { } //「空的」 方法定義 26: public void windowDeiconified(WindowEvent 事件) { } //「空的」 27: public void windowIconified(WindowEvent 事件) { } //「空的」 28: public void windowOpened(WindowEvent 事件) { } //「空的」方法 29: } //類別:傾聽者 定義區塊結束 程式執行結果
35
轉接類別事件處理 (8/12) 上列使用傾聽者介面WindowListener的範例中,傾聽者類別於宣告實作傾聽者介面WindowListener之後,需要將WindowListener介面的7個等待實作方法一一加以定義。 這7個等待實作方法包含windowActivated(WindowEvent 事件) 、windowClosed(WindowEvent 事件) 、windowClosing(WindowEvent 事件) 、windowDeactivated(WindowEvent 事件) 、windowDeiconified(WindowEvent 事件) 、windowlconified(WindowEvent 事件) 及windowOpened(WindowEvent 事件)。
36
轉接類別事件處理 (9/12) 我們可以看出實際上被定義的方法只有windowClosing(WindowEvent 事件)方法,而其他方法都是填入「空的」,不具任何程式碼的定義,這使得實作WindowListener介面的程式碼變得有一點冗長。 以下的範例使用轉接類別處理事件,因為轉接類別已經為所有的方法都填入基本的,「空的」,不具任何程式碼的定義了,所以惟有真正使用到的方法才需要加以定義。
37
轉接類別事件處理 (10/12) 1: //檔名:窗框關閉使用轉接類別測試.java 2: //說明:測試轉接類別用法
2: //說明:測試轉接類別用法 3: import java.applet.Applet; //引入Applet類別 4: import java.awt.Frame; //引入Button類別 5: import java.awt.event.WindowEvent; 6: import java.awt.event.WindowAdapter;
38
轉接類別事件處理 (11/12) 7: public class 窗框關閉使用轉接類別測試 extends Applet {
8: Frame 窗框; 9: public void init() { 10: 窗框 = new Frame("測試窗框"); 11: 窗框.setSize(200,200); 12: 窗框.setVisible(true); 13: 窗框.addWindowListener(new 傾聽者() ); 14: } 15: } //類別:窗框關閉使用轉接類別測試 定義區塊結束
39
轉接類別事件處理 (12/12) 16: class 傾聽者 extends WindowAdapter {
17: public void windowClosing (WindowEvent 事件) { 18: Object 物件=事件.getSource(); 19: Frame 窗框物件=(Frame)物件; 20: 窗框物件.dispose(); 21: } //方法:windowClosing定義區塊結束 22: } //類別:傾聽者 定義區塊結束 程式執行結果
40
內層類別事件處理 (1/7) 所謂內層類別(inner class)就是在類別中再定義的類別,內層類別中可以直接使用包含此內層類別的類別中的所有變數與方法,這使得內層類別的設計變得更為方便,擴大類別的應用層面。 內層類別分為具名(named)與匿名(anonymous)二種,以下我們將此二種內層類別應用於事件處理以便說明其應用。 我們首先說明具名內層類別的用法,以下範例程式即是使用具名內層類別的例子。
41
內層類別事件處理 (2/7) 1: //檔名:窗框關閉使用具名內層類別測試.java 2: //說明:測試具名內層類別用法
2: //說明:測試具名內層類別用法 3: import java.applet.Applet; //引入Applet類別 4: import java.awt.Frame; //引入Button類別 5: import java.awt.event.WindowEvent; 6: import java.awt.event.WindowAdapter; 7: public class 窗框關閉使用具名內層類別測試 extends Applet { 8: Frame 窗框; 9: public void init() {
42
內層類別事件處理 (3/7) 10: 窗框 = new Frame("測試窗框"); 11: 窗框.setSize(200,200);
12: 窗框.setVisible(true); 13: 窗框.addWindowListener(new 窗框轉接內層類別() ); 14: } //方法:init() 定義區塊結束 15: class 窗框轉接內層類別 extends WindowAdapter { 16: public void windowClosing (WindowEvent 事件) { 17: 窗框.dispose(); 18: } //方法:windowClosing定義區塊結束 19: } //內層類別:窗框轉接內層類別 定義區塊結束 20: } //類別:窗框關閉使用具名內層類別測試 定義區塊結束
43
內層類別事件處理 (4/7) 1: <html>
2: <applet code="窗框關閉使用具名內層類別測試.class" width="350" height="100"> 3: </applet> 4: </html> 程式執行結果
44
內層類別事件處理 (5/7) 以下為使用匿名內層類別的範例程式: 1: //檔名:窗框關閉使用匿名內層類別測試.java
2: //說明:測試匿名內層類別用法 3: import java.applet.Applet; //引入Applet類別 4: import java.awt.Frame; //引入Button類別 5: import java.awt.event.WindowEvent; 6: import java.awt.event.WindowAdapter; 7: public class 窗框關閉使用匿名內層類別測試 extends Applet { 8: Frame 窗框; 9: public void init() {
45
內層類別事件處理 (6/7) 10: 窗框 = new Frame("測試窗框"); 11: 窗框.setSize(200,200);
12: 窗框.setVisible(true); 13: 窗框.addWindowListener( 14: new WindowAdapter() { 15: public void windowClosing (WindowEvent 事件) { 16: 窗框.dispose(); 17: } //方法:windowClosing定義區塊結束 18: } //內層類別:WindowAdapter()建構方法 定義區塊結束 19: );//敘述:addWindowListener 結束 20: } //方法:init() 定義區塊結束 21: } //類別:窗框關閉使用匿名內層類別測試 定義區塊結束
46
內層類別事件處理 (7/7) 1: <html>
2: <applet code="窗框關閉使用匿名內層類別測試.class" width="350" height="100"> 3: </applet> 4: </html> 程式執行結果
47
Q&A
48
提 示 Java語言的圖形使用者介面是使用事件最頻繁的部分,當使用者操作圖形使用者介面中的某些元件時會產生事件,而這個事件將引發某些程式碼的執行,因而可讓圖形使用者介面與使用者之間有了互動(interaction)。
49
提 示 Component類別是所有的AWT圖形使用者介面類別的超類別,也就是說,所有的AWT圖形使用者介面類別都是Component類別的衍生類別。
50
提 示 Container類別的衍生類別主要有Window、Dialog、FileDialog、Frame、Panel、Applet等,在此類元件類別中可以再容納(加入)其他元件。
51
提 示 Window類別的衍生類別主要有Dialog、FileDialog、Frame等,此類元件類別可以於桌面上顯示窗框。
52
程式執行結果 (範例10-1.)
53
程式執行結果 (範例10-2.)
54
程式執行結果 (範例10-3.)
55
程式執行結果 (範例10-4.)
56
程式執行結果 (範例10-5.)
57
程式執行結果 (範例10-6.)
58
程式執行結果 (範例10-7.)
Similar presentations