[瘋狂Java筆記]事件處理:事件型別、監聽器介面、事件介面卡
1. 不同型別事件對應不同型別的監聽器介面:
1) 總的來說就是實現了該種類型的介面,就能監聽並處理該種類型的事件;
2) 常見的事件型別有ActionEvent、WindowEvent、TextEvent(文字框中產生的事件,比如正在輸入文字等)、MouseEvent(滑鼠事件)等;
3) AWT都分別為各種事件型別準備了監聽器介面:ActionListener、WindowListener、TextListener等,可以發現命名規律就是XxxEvent對應XxxListener介面;
4) 除了MouseEvent之外,MouseEvent對應了兩種監聽器介面,一個是普通的MouseListener(監聽並處理普通的滑鼠事件,如點選、鬆開等),但是滑鼠是一種特殊的輸入裝置,還具有拖動的效果,因此針對這種事件AWT還專門準備了MouseMotionListener介面專門用來監聽這種事件;
!!因此對於MouseEvent事件比較特殊,普通滑鼠事件和滑鼠拖動事件都屬於MouseEvent這一種類別,但是實際上系統會把這兩種動作的事件傳送給不同的監聽器,一種是MouseListener監聽器,一種是MouseMotionListener監聽器,實際程式設計時要注意,不要以為還有一種MouseMotionEvent的事件!!
2. 監聽器介面的方法:
1) 每種監聽器介面對應了一種型別的事件,比如ActionListener介面就代表了動作事件這一類事件,但介面中定義的每種方法分別用來處理該種類型事件的一小類;
2) 比如WindowListener介面中定義了7個方法,分別對應了視窗型別事件的7種事件,比如視窗開啟、縮小、關閉等,監聽器會根據具體發生的事件來呼叫對應的方法來處理,這個過程是自動的,當事件發生時並不是使用者呼叫這些方法處理,而是“監聽器”自動呼叫;
!!其實也不是監聽器自己呼叫的,而是虛擬機器(Java作業系統)呼叫的,即使用者寫的方法由作業系統來呼叫,這就是典型的回撥函式,將使用者的方法作為引數傳入作業系統提供的系統函式來執行,即作業系統的0級程式碼呼叫使用者寫的3級程式碼,就是這種關係;
!!只不過Java沒有函式的概念,全部都包裝成面向物件的類了;
3) 既然要實現監聽器介面,那就必須實現裡面的全部方法,比如WindowListener裡面的全部7個方法,一個都不能少(否則編譯報錯),但有些介面,比如ActionListener只有一個方法,那該介面就是一種函式式介面,可以使用Lambda表示式進行函式閉包;
!!雖然ActionListener只有一個方法,但並不代表ActionEvent就只有一種事件,其實有很多,按鈕單擊、選單項單擊等等,只不過具體發生的是什麼事件需要在方法體中判斷了;
3. ActionListener:
1) 只有一個方法來處理所有的ActionEvent事件:public void actionPerformed(ActionEvent e);
2) Java的Event型別的繼承結構是EventObject -> AWTEvent -> 各種Event(ActionEvent、WindowEvent等);
3) 常用方法:public String ActionEvent.getActionCommand(); // 獲取觸發ActionEvent的元件的命令名(比如對於按鈕就返回按鈕上的文字)
4. WindowListener示例:
1) 監聽器可以同時監聽多個元件就意味著監聽器也可以實現多種Listener介面,同時監聽多個、不同型別事件的元件;
2) 該示例中的監聽器同時實現兩種介面,一個ActionListener另一個WindowListener,並真正意義上實現程式可關閉;
3) 其實只要呼叫System.exit(0)就可以實現正常關閉;
4) 示例:
public class AwtTest {
Frame f = new Frame("WindowEvent Test");
TextArea ta = new TextArea(6, 40);
Button btn = new Button("button");
class Listener implements ActionListener, WindowListener {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
ta.append("Button pushed!\n");
}
@Override
public void windowOpened(WindowEvent e) { // 開啟
// TODO Auto-generated method stub
ta.append("Window opened!\n");
}
@Override
public void windowClosing(WindowEvent e) { // 正在關閉
// TODO Auto-generated method stub
ta.append("Window closing!\n");
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) { // 已關閉
// TODO Auto-generated method stub
ta.append("Window closed!\n");
}
@Override
public void windowIconified(WindowEvent e) { // 最小化
// TODO Auto-generated method stub
ta.append("Window iconified!\n");
}
@Override
public void windowDeiconified(WindowEvent e) { // 恢復
// TODO Auto-generated method stub
ta.append("Window deiconified!\n");
}
@Override
public void windowActivated(WindowEvent e) { // 得到焦點
// TODO Auto-generated method stub
ta.append("Window activated!\n");
}
@Override
public void windowDeactivated(WindowEvent e) { // 失去焦點
// TODO Auto-generated method stub
ta.append("Window deactivated!\n");
}
}
public void init() {
f.add(ta);
f.add(btn, BorderLayout.SOUTH);
Listener l = new Listener();
f.addWindowListener(l);
btn.addActionListener(l);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
new AwtTest().init();
}
}
!當System.exit的退出碼為0時表示程式正常退出;
!!通常不建議一個監聽器實現多個Listener介面,因為這不符合科學的設計模式,還是分工分模組為好,儘量減弱軟體的模組耦合度;
5. 事件介面卡:
1) 由於要實現Listener介面就必須實現其中的全部方法,但大多數情況下並不需要實現全部方法而只想實現感興趣的那幾個方法,但即使其他方法不感興趣也不得不加上那幾個方法的空方法體,顯得非常多此一舉;
2) 因此AWT還提供了事件介面卡,它就是一個類,只不過實現了對應的監聽器介面,併為每個方法提供過了一個空的方法體,因此要實現監聽器功能的時候就沒必要直接實現對應的介面了,只要繼承相應的介面卡,然後選擇你感興趣的方法實現就行了,不需要實現介面中的所有方法;
3) 介面和介面卡命名的規則:XxxListener對應XxxAdapter
4) 示例:只需要實現感興趣的方法就行哦!
public class AwtTest {
Frame f = new Frame("WindowAdapter Test");
class Listener extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
// super.windowClosing(e);
System.exit(0);
}
}
public void init() {
f.addWindowListener(new Listener());
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
new AwtTest().init();
}
}