在 JPanel 子類中添加 KeyListener,keyTyped 方法內判斷 VK_0 卻無任何控制台輸出。
只有擁有鍵盤焦點的組件才能接收鍵盤事件。 JPanel 默認 focusable = false,且未主動請求焦點。
setFocusable(true)。addNotify() 或外部調用)執行 requestFocusInWindow()。public class MyPanel extends JPanel {
public MyPanel() {
setFocusable(true); // 關鍵1
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) { // 建議用 keyPressed 捕獲功能鍵
if (e.getKeyCode() == KeyEvent.VK_0) {
System.out.println("press 0");
}
}
});
}
@Override
public void addNotify() {
super.addNotify();
requestFocusInWindow(); // 關鍵2:加入容器時自動請求焦點
}
}
public class MyPanel extends JPanel {
public MyPanel() {
// 1. 定義動作
Action pressZero = new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
System.out.println("press 0 via Key Bindings");
}
};
// 2. 綁定鍵盤觸發條件:WHEN_IN_FOCUSED_WINDOW = 窗口焦點時生效(不要求組件焦點)
InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_0, 0), "pressZero");
am.put("pressZero", pressZero);
}
}
| 特性 | KeyListener | Key Bindings |
|---|---|---|
| 焦點依賴 | 強依賴(組件必須聚焦) | 可選(WHEN_IN_FOCUSED_WINDOW 無需組件焦點) |
| 功能鍵支援 | keyPressed 可捕獲 | 原生支援所有鍵 |
| 組合鍵 | 需手動判斷修飾鍵 | KeyStroke.getKeyStroke("ctrl Shift Z") 直觀 |
| 可維護性 | 分散在匿名類 | 動作與觸發分離,易複用/解綁 |
| 推薦場景 | 簡單原型、臨時測試 | 正式項目、複雜快捷鍵體系 |
keyTyped 無法捕獲功能鍵(F1、方向鍵、修飾鍵),必須用 keyPressed/keyReleased。requestFocusInWindow() 最後調用,或用 FocusTraversalPolicy 控制順序。拋棄 KeyListener,擁抱 Key Bindings,徹底告別「焦點丟失導致鍵盤無響應」的歷史包袱。