5.2.1 事件類
與AWT有關的所有事件類都由java.awt.AWTEvent類派生,它也是EventObject類的子類。AWT事件共有10類,可以歸為兩大類:低級事件和高級事件。
java.util.EventObject類是所有事件對象的基礎父類,所有事件都是由它派生出來的。AWT的相關事件繼承于java.awt.AWTEvent類,這些AWT事件分為兩大類:低級事件和高級事件,低級事件是指基于組件和容器的事件,當一個組件上發生事件,如:鼠標的進入,點擊,拖放等,或組件的窗口開關等,觸發了組件事件。高級事件是基于語義的事件,它可以不和特定的動作相關聯,而依賴于觸發此事件的類,如在TextField中按Enter鍵會觸發ActionEvent事件,滑動滾動條會觸發AdjustmentEvent事件,或是選中項目列表的某一條就會觸發ItemEvent事件。
◇ 低級事件 ComponentEvent( 組件事件:組件尺寸的變化,移動) ContainerEvent( 容器事件:組件增加,移動) WindowEvent( 窗口事件:關閉窗口,窗口閉合,圖標化) FocusEvent( 焦點事件:焦點的獲得和丟失) KeyEvent( 鍵盤事件:鍵按下、釋放) MouseEvent( 鼠標事件:鼠標單擊,移動)
◇ 高級事件(語義事件) ActionEvent(動作事件:按鈕按下,TextField中按Enter鍵) AdjustmentEvent(調節事件:在滾動條上移動滑塊以調節數值) ItemEvent(項目事件:選擇項目,不選擇"項目改變") TextEvent(文本事件,文本對象改變)
5.2.2 事件監聽器
每類事件都有對應的事件監聽器,監聽器是接口,根據動作來定義方法。
例如,與鍵盤事件KeyEvent相對應的接口是: public interface KeyListener extends EventListener { public void keyPressed(KeyEvent ev); public void keyReleased(KeyEvent ev); public void keyTyped(KeyEvent ev); }
注意到在本接口中有三個方法,那么java運行時系統何時調用哪個方法?其實根據這三個方法的方法名就能夠知道應該是什么時候調用哪個方法執行了。當鍵盤剛按下去時,將調用keyPressed( )方法執行,當鍵盤抬起來時,將調用keyReleased( )方法執行,當鍵盤敲擊一次時,將調用keyTyped( )方法執行。
又例如窗口事件接口: public interface WindowListener extends EventListener{ public void windowClosing(WindowEvent e); //把退出窗口的語句寫在本方法中 public void windowOpened(WindowEvent e); //窗口打開時調用 public void windowIconified(WindowEvent e); //窗口圖標化時調用 public void windowDeiconified(WindowEvent e); //窗口非圖標化時調用 public void windowClosed(WindowEvent e); //窗口關閉時調用 public void windowActivated(WindowEvent e); //窗口激活時調用 public void windowDeactivated(WindowEvent e); //窗口非激活時調用 }
AWT的組件類中提供注冊和注銷監聽器的方法:
◇ 注冊監聽器: public void add (listener);
◇ 注銷監聽器: public void remove (listener);
例如Button類:(查API) public class Button extends Component { …… public synchronized void addActionListener(ActionListener l); public synchronized void removeActionListener(ActionListener l); ……}
5.2.3 AWT事件及其相應的監聽器接口(1)
5.2.3 AWT事件及其相應的監聽器接口(2)
例5.10說明事件處理模型的應用。
例5.10 import java.awt.*; import java.awt.event.*; public class ThreeListener implements MouseMotionListener,MouseListener,WindowListener { //實現了三個接口 private Frame f; private TextField tf; public static void main(String args[]) { ThreeListener two = new ThreeListener(); two.go(); }
public void go() { f = new Frame("Three listeners example"); f.add(new Label("Click and drag the mouse"),"North"); tf = new TextField(30); f.add(tf,"South"); //使用缺省的布局管理器 f.addMouseMotionListener(this); //注冊監聽器MouseMotionListener f.addMouseListener(this); //注冊監聽器MouseListener f.addWindowListener(this); //注冊監聽器WindowListener f.setSize(300,200); f.setVisible(true); }
public void mouseDragged (MouseEvent e) { //實現mouseDragged方法 String s = "Mouse dragging : X="+e.getX()+"Y = "+e.getY(); tf.setText(s); } public void mouseMoved(MouseEvent e){} //對其不感興趣的方法可以方法體為空 public void mouseClicked(MouseEvent e){} public void mouseEntered(MouseEvent e){ String s = "The mouse entered"; tf.setText(s); }
public void mouseExited(MouseEvent e){ String s = "The mouse has left the building"; tf.setText(s); }
public void mousePressed(MouseEvent e){} public void mouseReleased(MouseEvent e){ } public void windowClosing(WindowEvent e) { //為了使窗口能正常關閉,程序正常退出,需要實現windowClosing方法 System.exit(1); }
public void windowOpened(WindowEvent e) {} //對其不感興趣的方法可以方法體為空 public void windowIconified(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowActivated(WindowEvent e) { } public void windowDeactivated(WindowEvent e) {}
}
上例中有如下幾個特點: 1.可以聲明多個接口,接口之間用逗號隔開。 ……implements MouseMotionListener, MouseListener, WindowListener; 2.可以由同一個對象監聽一個事件源上發生的多種事件: f.addMouseMotionListener(this); f.addMouseListener(this); f.addWindowListener(this); 則對象f 上發生的多個事件都將被同一個監聽器接收和處理。
3.事件處理者和事件源處在同一個類中。本例中事件源是Frame f,事件處理者是類ThreeListener,其中事件源Frame f是類ThreeListener的成員變量。
4.可以通過事件對象獲得詳細資料,比如本例中就通過事件對象獲得了鼠標發生時的坐標值。 public void mouseDragged(MouseEvent e) { String s="Mouse dragging :X="+e.getX()+"Y="+e.getY(); tf.setText(s); }
Java語言類的層次非常分明,因而只支持單繼承,為了實現多重繼承的能力,Java用接口來實現,一個類可以實現多個接口,這種機制比多重繼承具有更簡單、靈活、更強的功能。在AWT中就經常用到聲明和實現多個接口。記住無論實現了幾個接口,接口中已定義的方法必須一一實現,如果對某事件不感興趣,可以不具體實現其方法,而用空的方法體來代替。但卻必須所有方法都要寫上。
5.2.4 事件適配器
Java語言為一些Listener接口提供了適配器(Adapter)類。可以通過繼承事件所對應的Adapter類,重寫需要方法,無關方法不用實現。事件適配器為我們提供了一種簡單的實現監聽器的手段, 可以縮短程序代碼。但是,由于java的單一繼承機制,當需要多種監聽器或此類已有父類時,就無法采用事件適配器了。
1.事件適配器--EventAdapter
下例中采用了鼠標適配器: import java.awt.*; import java.awt.event.*; public class MouseClickHandler extends MouseAdaper{ public void mouseClicked(MouseEvent e) //只實現需要的方法 { ……} }
java.awt.event包中定義的事件適配器類包括以下幾個: 1.ComponentAdapter( 組件適配器) 2.ContainerAdapter( 容器適配器) 3.FocusAdapter( 焦點適配器) 4.KeyAdapter( 鍵盤適配器) 5.MouseAdapter( 鼠標適配器) 6.MouseMotionAdapter( 鼠標運動適配器) 7.WindowAdapter( 窗口適配器)
2. 用內部類實現事件處理
內部類(inner class)是被定義于另一個類中的類,使用內部類的主要原因是由于: ◇ 一個內部類的對象可訪問外部類的成員方法和變量,包括私有的成員。 ◇ 實現事件監聽器時,采用內部類、匿名類編程非常容易實現其功能。 ◇ 編寫事件驅動程序,內部類很方便。 因此內部類所能夠應用的地方往往是在AWT的事件處理機制中。
例5.11 import java.awt.* ; import java.awt.event.*; public class InnerClass{ private Frame f; private TextField tf; public InnerClass(){ f=new Frame("Inner classes example"); tf=new TextField(30); }
public voidi launchFrame(){ Label label=new Label("Click and drag the mouse"); f.add(label,BorderLayout.NORTH); f.add(tf,BorderLayout.SOUTH); f.addMouseMotionListener(new MyMouseMotionListener());/*參數為內部類對象*/ f.setSize(300,200); f.setVisible(true); }
class MyMouseMotionListener extends MouseMotionAdapter{ /*內部類開始*/ public void mouseDragged(MouseEvent e) { String s="Mouse dragging: x="+e.getX()+"Y="+e.getY(); tf.setText(s); } } ;
public static void main(String args[]) { InnerClass obj=new InnerClass(); obj.launchFrame(); } }//內部類結束 }
|