第 17 章 有來有往 互動式視窗程式 1
本章提要 17.1 前言 17.2 元件 Event 觸發 17.3 Event 監聽者 Listener 17.4 Event 接收者 Adapter 17.5 Event 類別及提供的函式 17.5.1 MouseEvent 17.5.2 KeyEvent 17.5.3 TextEvent 17.5.4 WindowEvent 17.5.5 其他 Event 17.6 後記 2
17.1 前言 為了讓視窗程式能夠達到與使用者互動的目的, 我們必須讓這些按鈕 選單等元件有生命會隨著使用者鍵入字元 按下 Enter 滑鼠點選 滾動捲軸而做出正確的動作該如何付予這些元件生命, 讓元件肯聽命行事呢 3
17.2 元件 Event 觸發 當我們執行按按鈕 拉下拉式選單 轉動捲軸 點選選單 輸入文字到文字框中 放大縮小視窗等動作對元件而言, 就像觸發了某項事件 (Event) 一樣例如按按鈕, 就是利用滑鼠在按鈕上敲擊一下, 相當於 mouseclicked Event 發生我們就必須針對事件作出相對的反應 4
17.2 元件 Event 觸發 可能的 Event ActionEvent: 元件被 Click 或 Change 會發生此 Event 的元件有 Button List MenuItem TextField AdjustmentEvent 轉動捲軸 會發生此 Event 的元件有 Scrollbar ContainerEvent 將元件加入或移除 會發生此 Event 的元件有 Container Dialog Frame Panel Scrollbar Window 等 5
17.2 元件 Event 觸發 ComponentEvent 元件釋放 隱藏 顯示 放大 縮小 移動 會發生此 Event 的元件有 Button Checkbox Choice Container Dialog Frame Label List Panel Scrollbar TextArea TextComponent TextField Window 等 FocusEvent 元件取得或失去控制權 會發生此 Event 的元件有 Button Checkbox Choice Container Dialog Frame Label List Panel Scrollbar TextArea TextComponent TextField Window 等 6
17.2 元件 Event 觸發 ItemEvent 有多個選項進行選擇時 會發生此 Event 的元件有 List Checkbox Choice 等 KeyEvent 鍵盤有鍵入動作 會發生此 Event 的元件有 Button Checkbox Choice Component Container Dialog Frame Label List Panel Scrollbar ScrollPanel TextArea TextComponent TextField Window 等 7
17.2 元件 Event 觸發 MouseEvent 滑鼠有按下 釋放 敲擊等動作 會發生此 Event 的元件有 Button Checkbox Choice Component Container Dialog Frame Label List Panel Scrollbar ScrollPanel TextArea TextComponent TextField Window 等 MouseMotionEvent 滑鼠有下拉 移動等動作 會發生此 Event 的元件有 Button Checkbox Choice Component Container Dialog Frame Label List Panel Scrollbar ScrollPanel TextArea TextComponent TextField Window 等 8
17.2 元件 Event 觸發 PaintEvent 元件被繪出 (paint) 或重繪 (repaint) 會發生此 Event 的元件有 Panel 等 TextEvent TextArea TextField TextComponent 裡面的文字被修改 WindowEvent 視窗縮小 放大 關閉 會發生此 Event 的元件有 Dialog Frame Window 等 9
17.2 元件 Event 觸發 當有 Event 被觸發時, 元件必須做出相對應的反應元件就將偵測的工作委託給監聽者 (Listener) 或接收者 (Adapter) 負責由 Listener 或 Adapter 幫元件偵測看有沒有 Event 發生, 並且做出回應 10
17.3 Event 監聽者 Listener 每個元件旁邊都有幾個專屬的服務生, 幫忙處理滑鼠 鍵盤 視窗 文字等 Event, 而這些服務生就是 1. Listener 2. Adapter 針對不同的 Event,Java 會派遺不同的 Listener 或 Adapter 應付, 以達到 兵來將擋, 水來土掩 的效果針對 MouseEvent,Java 利用 MouseListener 來做偵測及回應針對 KeyEvent,Java 則利用 KeyListener 來對付 11
17.3 Event 監聽者 Listener MouseListener 是一個 Interface 項次 1 2 3 4 5 MouseListener 的方法 mouseclicked(mouseevent e) 當滑鼠完成按一下動作時觸發, 即在元件上按下滑鼠左鍵並放開 mouseentered(mouseevent e) 當滑鼠進入元件時觸發 mouseexited(mouseevent e) 當滑鼠離開元件時觸發 mousepressed(mouseevent e) 當滑鼠在元件上按下左鍵時觸發 mousereleased(mouseevent e) 當滑鼠放開左鍵時觸發 12
17.3 Event 監聽者 Listener 由於 MouseListener 只是一個介面為了讓 MouseListener 能夠執行, 須建立一個類別, 這個類別實作 MouseListener 提供的所有函式當元件需要用到 MouseListener 來偵測滑鼠動作時, 就利用元件提供的 addmouselistener 將該類別產生的實例加到元件上 13
範例程式 1 建立可以互動的 button 6 import java.awt.event.*; 7 8 class buttonimp implements MouseListener 9 { 10 public void mouseclicked(mouseevent e) { 11 System.out.println(" 滑鼠按一下!!"); 12 } 13 public void mousepressed(mouseevent e) { 14 System.out.println(" 滑鼠按下..."); 15 } 14
範例程式 1 建立可以互動的 button 16 public void mousereleased(mouseevent e) { 17 System.out.println(" 滑鼠放開!"); 18 } 19 public void mouseentered(mouseevent e) { 20 System.out.println(" 滑鼠進入 ~~"); 21 } 22 public void mouseexited(mouseevent e) { 23 System.out.println(" 滑鼠離開."); 24 } 25 } 32 Button btn1 = new Button(" 這是 Button"); 33 btn1.addmouselistener(new buttonimp()); 34 add(btn1); 15
執行結果 滑鼠進入 ~~ 滑鼠離開. 滑鼠進入 ~~ 滑鼠按下... 滑鼠放開! 滑鼠按一下!! 滑鼠離開. 16
17.3 Event 監聽者 Listener Event Listener Listener 提供的函式介面 ActionEvent ActionListener actionperformed(actionevent e) AdjustmentEvent ContainerEvent ComponentEvent FocusEvent AdjustmentListener ContainerListener ComponentListener FocusListener adjustmentvaluechanged(adjustmenteve nt e) componentadded(containerevent e) componentremoved(containerevent e) componentadded(containerevent e) componentremoved(containerevent e) focusgained(focusevent e) focuslost(focusevent e) ItemEvent ItemListener itemstatechanged(itemevent e) KeyEvent KeyListener keypressed(keyevent e) keyreleased(keyevent e) keytyped(keyevent e) 17
MouseEvent MouseMotionEve nt PaintEvent MouseListener MouseMotionListen er PaintListener mouseclicked(mouseevent e) mouseentered(mouseevent e) mouseexited(mouseevent e) mousepressed(mouseevent e) mousereleased(mouseevent e) mousedragged(mouseevent e) mousemoved(mouseevent e) componentadded(containerevent e) componentremoved(containerevent e) TextEvent TextListener textvaluechanged(textevent e) WindowEvent WindowListener windowactivated(windowevent e) windowclosed(windowevent e) windowclosing(windowevent e) windowdeactivated(windowevent e) windowdeiconified(windowevent e) windowiconified(windowevent e) windowopened(windowevent e) 18
17.4 Event 接收者 Adapter 利用 implements 的方式建立類別, 我們必需實作 Listener 裡面的每個函式即使沒有使用到的函式, 也必須寫出來有沒有其他辦法能夠達到相同的目的, 而不須重寫每個函式呢? Adapter 19
範例程式 2 以 Adaptor 方式建立可以互動的 button 8 class buttona extends MouseAdapter 9 { 10 public void mouseclicked(mouseevent e) { 11 System.out.println("Mouse clicked event happened!!"); 12 } 13 public void mousepressed(mouseevent e) { 14 System.out.println("Mouse is pressed..."); 15 } 16 } 18 class buttonb extends MouseAdapter 19 { 20 public void mouseentered(mouseevent e) { 21 System.out.println("Mouse Entered~"); 22 } 23 public void mouseexited(mouseevent e) { 24 System.out.println("Mouse Exited."); 25 } 26 } 20
33 btn1.addmouselistener(new buttona()); 34 add(btn1); 35 Button btn2 = new Button("B"); 36 btn2.addmouselistener(new buttonb()); 37 add(btn2); 執行結果 Mouse Entered~ Mouse Exited. Mouse Entered~ Mouse Exited. Mouse Entered~ Mouse Exited. Mouse is pressed... Mouse clicked event happened!! Mouse is pressed... Mouse clicked event happened!! Mouse Entered~ Mouse Exited. 21
17.4 Event 接收者 Adapter 另一種程式的寫法, 我們直接將程式寫在元件的函式輸入參數中 btn1.addmouselistener(new buttona()); btn1.addmouselistener( new MouseAdapter() { public void mouseclicked(mouseevent e) { System.out.println("Mouse clicked event happend!!");} }); 22
範例程式 3 利用 adapter 處理 MouseEvent 13 Button btn1 = new Button("A"); 14 btn1.addmouselistener(new MouseAdapter (){ 15 public void mouseclicked(mouseevent e) { 16 System.out.println("Mouse clicked event happend!!"); 17 } 18 public void mousepressed(mouseevent e) { 19 System.out.println("Mouse be pressed..."); 20 } 21 }); 22 add(btn1); 23 Button btn2 = new Button("B"); 24 btn2.addmouselistener(new MouseAdapter(){ 25 public void mouseentered(mouseevent e) { 26 System.out.println("Mouse Entered~"); 27 } 28 public void mouseexited(mouseevent e) { 29 System.out.println("Mouse Exited."); 30 } 31 }); 23
17.5 Event 類別及提供的函式 當我們在監控時, 我們可能會想要知道 Event 發生時的座標 次數 狀態等資訊例如, 滑鼠所按的元件, 座標位置為何, 鍵盤輸入的值是什麼, 是不是有配合 Alter 鍵或 Shift 鍵一起按等要如何才能得到這些資訊呢? 24
17.5.1 MouseEvent MouseEvent 的建構元 項次 1 MouseEvent 的建構元 MouseEvent(Component source, int id, long when, int modifiers, int x, int y, int clickcount, boolean popuptrigger) 建立一個 MouseEvent 的實例, 用來記錄當滑鼠有動作時的相關資訊 :source 表示處理的元件為何 ;id 表示元件的識別碼 ;when 表示動作發生的時間 ;modifiers 表示是不是有伴隨著 Alt Ctrol 或 Shitf 一起按 ;x 表示動作發生的 x 座標 ;y 表示動作發生的 y 座標 ;clickcount 表示執行的次數 ;popuptrigger 表示所處理的元件是不是按右鍵所彈跳出來的 menu 25
範例程式 4 MouseEvent 的各項參數 8 class mousea extends MouseAdapter 9 { 10 public void mouseclicked(mouseevent e) { 11 System.out.println(" 目前按的按鈕是 :" + e.getbutton()); 12 System.out.println(" 被按的次數 :" + e.getclickcount()); 13 System.out.println(" 座標 :" + e.getpoint()); 14 System.out.println("x 軸 :" + e.getx()); 15 System.out.println("y 軸 :" + e.gety()); 16 System.out.println(" 是不是 popupmenu:" + e.ispopuptrigger() ); 17 System.out.println("e 的參數 :" + e.paramstring()); 18 } 19 } 20 26
26 Button btn1 = new Button("A"); 27 btn1.addmouselistener(new mousea()); 執行結果 目前按的按鈕是 :1 被按的次數 :1 座標 :java.awt.point[x=9,y=8] x 軸 :9 y 軸 :8 是不是 popupmenu:false e 的參數 :MOUSE_CLICKED,(9,8),button=1,modifiers=Button1,clickCount=1 目前按的按鈕是 :3 被按的次數 :1 座標 :java.awt.point[x=9,y=8] x 軸 :9 y 軸 :8 是不是 popupmenu:false e 的參數 :MOUSE_CLICKED,(9,8),button=3,modifiers=Meta+Shift+Button3, extmodifiers=shift,clickcount=1 目前按的按鈕是 :1 被按的次數 :2 座標 :java.awt.point[x=9,y=8] x 軸 :9 y 軸 :8 是不是 popupmenu:false e 的參數 :MOUSE_CLICKED,(9,8),button=1,modifiers=Button1,clickCount=2 27
17.5.2 KeyEvent KeyEvent 的建構元 項次 1 KeyEvent 的建構元 KeyEvent(Component source, int id, long when, int modifiers, int keycode, char keychar, int keylocation) 28
項次 1 2 3 4 5 char getkeychar() 傳回鍵盤鍵入的字元 KeyEvent 的方法 int getkeycode() 傳回鍵盤鍵入字元的 ASCII 碼 String getkeytext(int keycode) 傳回 keycode 的敘述, 如按下倒退鍵, 則傳回 Backspace 字串 long getwhen() 傳回時間 boolean isaltdown() boolean iscontroldown() boolean isshiftdown () 傳回是否有按下 Alt Ctrl 或 Shift 29
範例程式 5 KeyEvent 的各項參數 8 class keya extends KeyAdapter 9 { 10 public void keypressed(keyevent e) { 11 System.out.println(" 鍵入的字元是 :" + e.getkeychar()); 12 System.out.println(" 字元的 code:" + e.getkeycode()); 13 System.out.println("code 的名稱 :" + e.getkeytext(e.getkeycode())); 14 System.out.println("e 的參數 :" + e.paramstring()); 15 } 16 } 30
23 TextArea tx1 = new TextArea(5, 20); 24 tx1.addkeylistener(new keya()); 執行結果 鍵入的字元是 :A 字元的 code:65 code 的名稱 :A e 的參數 : KEY_PRESSED,keyCode=65,keyChar='A',keyLocation=KEY_LOCATION_STANDARD 鍵入的字元是 :B 字元的 code:66 code 的名稱 :B e 的參數 : KEY_PRESSED,keyCode=66,keyChar='B',keyLocation=KEY_LOCATION_STANDARD 鍵入的字元是 : 字元的 code:8 code 的名稱 :Backspace e 的參數 :KEY_PRESSED,keyCode=8,Backspace,keyLocation=KEY_LOCATION_STANDARD 鍵入的字元是 :? 字元的 code:112 code 的名稱 :F1 e 的參數 :KEY_PRESSED,keyCode=112,F1,keyLocation=KEY_LOCATION_STANDARD 鍵入的字元是 :? 字元的 code:36 code 的名稱 :Home e 的參數 :KEY_PRESSED,keyCode=36,Home,keyLocation=KEY_LOCATION_STANDARD 31
17.5.3 TextEvent TextEvent 的建構元 項次 TextEvent 的建構元 1 TextEvent(Object source, int id) 項次 1 String paramstring() 回傳所有的參數 TextEvent 的方法 32
範例程式 6 TextEvent 的各項參數 8 class texta implements TextListener 9 { 10 public void textvaluechanged(textevent e) { 11 System.out.println("e 的參數 :" + e.paramstring()); 12 } 13 } 15 public class ch17_fram_textevent extends Frame 16 { private TextArea tx1, tx2, tx3; 17 public ch17_fram_textevent(){ 18 setlayout(new FlowLayout()); 19 setbounds(100, 100, 300, 300); 20 tx1 = new TextArea(2, 10); 21 tx2 = new TextArea(2, 10); 22 add(tx1); 23 add(tx2); 24 tx3 = new TextArea(4, 20); 25 tx3.addtextlistener(new texta()); 26 add(tx3); 33
27 Button btn = new Button("ADD"); 28 btn.addmouselistener(new MouseAdapter(){ 29 public void mousepressed(mouseevent e){ 30 String s = tx1.gettext()+tx2.gettext(); 31 tx3.settext(s); 32 } 33 }); 34
17.5.4 WindowEvent 項次 1 WindowEvent 的建構元 WindowEvent(Window source, int id, Window opposite, int oldstate, int newstate) 項次 1 2 3 int getnewstate() 回傳視窗的新狀態 int getoldstate() 回傳視窗的舊狀態 Window getwindow() 回傳原本的視窗 WindowEvent 的方法 35
8 class windowa extends WindowAdapter 9 { 10 public void windowactivated(windowevent e) { 11 System.out.println(" 視窗正在執行 "); } 13 public void windowclosing(windowevent e) { 14 System.out.println(" 再見..."); 15 System.exit(0); } 17 public void windowdeactivated(windowevent e) { 18 System.out.println(" 視窗非正在執行之視窗 "); } 20 public void windowdeiconified(windowevent e) { 21 System.out.println(" 視窗回復成原來的 size"); } 23 public void windowgainedfocus(windowevent e){ 24 System.out.println(" 視窗取得焦點 "); } 26 public void windowiconified(windowevent e) { 27 System.out.println(" 將視窗最小化 "); } 29 public void windowlostfocus(windowevent e) { 30 System.out.println(" 視窗失去焦點 "); } 32 } 36
執行結果 將視窗最小化視窗非正在執行之視窗視窗回復成原來的 size 視窗正在執行再見... 37
17.6 後記 視窗程式元件豐富了使用者視覺上的享受 若能夠賦予這些元件生命, 讓元件能夠與使用者有互動的效果, 則更能提升使用者的滿意度利用 Listener 或 Adapter 來製造元件的監聽者或接受者, 讓每個元件都有隨伺在旁的服務生, 幫元件做偵測及反應若能善加利用這些服務生, 我們就能針對不同的事件 (Event) 做出不同的反應 38