Applet (AWT 1.0/1.1 事件模型) 採用事件委派模型:事件源 (組件) 產生事件對象 → 註冊的監聽器接收處理。雖然現代 Swing/JavaFX 統一為 java.awt.event 套件,但理解 AWT 早期 Event 類與 handleEvent()、mouseDown() 等舊版事件處理方法,有助於閱讀舊代碼、把握事件傳遞本質。
所有方法回傳 boolean:true 表示已處理,阻止向上傳遞;false 繼續傳遞給父容器。
| 事件 | 方法簽名 | 觸發時機 | 參數說明 |
|---|---|---|---|
| 按下 | boolean mouseDown(Event e, int x, int y) | 滑鼠鍵按下瞬間 | e: 事件對象; x,y: 相對組件左上角座標 |
| 釋放 | boolean mouseUp(Event e, int x, int y) | 滑鼠鍵釋放瞬間 | 同上 |
| 移動 (無按鍵) | boolean mouseMove(Event e, int x, int y) | 滑鼠在組件上移動 | 高頻觸發,慎用重邏輯 |
| 拖曳 (按住移動) | boolean mouseDrag(Event e, int x, int y) | 按住滑鼠鍵並移動 | 同上 |
| 進入區域 | boolean mouseEnter(Event e, int x, int y) | 滑鼠進入組件邊界 | 同上 |
| 離開區域 | boolean mouseExit(Event e, int x, int y) | 滑鼠移出組件邊界 | 同上 |
注意:AWT 1.0 單鍵滑鼠模型,不區分左右鍵;Event 對象封裝座標、修飾鍵 (Shift/Ctrl/Meta)、點擊次數等。
| 事件 | 方法簽名 | 觸發時機 | 關鍵參數 |
|---|---|---|---|
| 按下 | boolean keyDown(Event e, int key) | 鍵盤按下 | key: 虛擬鍵碼 (見下表) |
| 釋放 | boolean keyUp(Event e, int key) | 鍵盤釋放 | 同上 |
| 常量 | 對應鍵 | 常量 | 對應鍵 |
|---|---|---|---|
Event.UP | ↑ | Event.F1~F12 | 功能鍵 |
Event.DOWN | ↓ | Event.HOME | Home |
Event.LEFT | ← | Event.END | End |
Event.RIGHT | → | Event.PGUP | Page Up |
Event.PGDN | Page Down |
字母數字鍵直接用 ASCII 碼 (如 'A', '1');key 參數為 int,字符需轉型 (char)key。
public class FollowMouse extends Applet {
int cx = 50, cy = 50; // 初始座標
public boolean mouseDown(Event e, int x, int y) {
cx = x; cy = y; // 更新座標
repaint(); // 排程重繪
return true; // 事件已處理
}
public void paint(Graphics g) {
g.drawString("在哪兒按滑鼠,我就在哪出現!", cx, cy);
}
}
流程:初始 paint() 顯示預設位置 → 用戶點擊 → mouseDown() 更新座標 → repaint() 觸發新 paint() → 字串跳轉至點擊處。
public class MouseMood extends Applet {
String msg = "";
public boolean mouseEnter(Event e, int x, int y) {
msg = "你進來了,真討厭!拿開!拿開!!";
repaint(); return true;
}
public boolean mouseExit(Event e, int x, int y) {
msg = "你把滑鼠移開了,別走嘛!為什麼不移進來?";
repaint(); return true;
}
public void paint(Graphics g) {
g.drawString(msg, 4, 20);
}
}
public class KeyMover extends Applet {
char pressKey = 0;
int outX = 5, outY = 15;
public boolean keyDown(Event e, int key) {
switch (key) {
case Event.UP: outY--; break;
case Event.DOWN: outY++; break;
case Event.LEFT: outX--; break;
case Event.RIGHT: outX++; break;
case Event.HOME: outX = 5; outY = 15; break;
case Event.END: outX = 5; outY = size().height - 15; break;
case Event.PGUP: outY -= 5; break;
case Event.PGDN: outY += 15; break;
default: pressKey = (char) key; break; // 普通字符
}
repaint(); return true;
}
public void paint(Graphics g) {
if (pressKey != 0)
g.drawString("你按下了:" + pressKey + " 鍵", outX, outY);
}
}
前置條件:Applet 區域必須先獲得焦點 (滑鼠點一下) 才能接收鍵盤事件。
| 維度 | AWT 1.0 (舊版) | AWT 1.1+ / Swing (現代) | JavaFX |
|---|---|---|---|
| 核心機制 | 繼承組件覆寫 mouseDown() 等方法 | 事件源 + 監聽器介面 (MouseListener 等) + 註冊 addXxxListener() | 事件源 + EventHandler / Lambda + setOnXxx() |
| 事件對象 | java.awt.Event (單一巨石類) | MouseEvent, KeyEvent, ActionEvent 等專用類 | MouseEvent, KeyEvent (FX 專用包) |
| 多監聽器 | 不支援 (單一方法) | 支援多個監聽器鏈 | 支援多處理器 |
| 事件消費 | 回傳 true | event.consume() | event.consume() |
| 座標系統 | 相對組件 | getX()/getY() (相對組件), getPoint(), getLocationOnScreen() | getX()/getY() (相對場景/節點) |
// 滑鼠點擊 -> 彈出座標
component.addMouseListener(new MouseAdapter() {
@Override public void mousePressed(MouseEvent e) {
System.out.println("Clicked at: " + e.getPoint());
}
});
// 鍵盤輸入 -> 顯示字符
component.addKeyListener(new KeyAdapter() {
@Override public void keyTyped(KeyEvent e) {
System.out.println("Typed: " + e.getKeyChar());
}
});
mouseMove/mouseDrag 極高頻,避免在內部執行複雜計算/IO;必要時用標誌位+定時器批次處理。setFocusable(true)、requestFocusInWindow()。SwingUtilities.convertPoint() 統一座標空間。consume() 阻止預設行為 (如 JTextField 吞噬特定按鍵);舊版回傳 true。Event 類及 handleEvent() 等方法標註 @Deprecated,新代碼請勿使用。