You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java AWT中通过KeyEventDispatcher获取按键码及识别组合键

问题解决:KeyEventDispatcher重复触发与组合键识别

为什么dispatch方法会多次执行?

AWT的KeyEvent包含三种触发时机:

  • KEY_PRESSED:按键按下瞬间
  • KEY_TYPED:生成可打印字符时触发(仅普通字符键会触发,功能键如方向键、F键不会)
  • KEY_RELEASED:按键松开瞬间

你看到的三次执行对应这三个事件,功能键因为没有KEY_TYPED事件,所以只触发两次。解决核心是只处理你需要的事件类型。

修正后的完整代码

下面的代码解决了重复触发问题,同时支持组合键识别,允许你自定义显示内容:

import java.awt.*;
import java.awt.event.*;

public class KeyEventInterceptionExample {
    private static StringBuilder keyBuffer = new StringBuilder();
    private static TextArea textArea;

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            Frame frame = new Frame("Key Event Interception Example");

            textArea = new TextArea();
            textArea.setEditable(false);
            textArea.setBounds(20, 30, 300, 150);

            MyKeyEventDispatcher keyEventDispatcher = new MyKeyEventDispatcher();
            KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keyEventDispatcher);

            frame.add(textArea);
            frame.setSize(350, 220);
            frame.setLayout(null);
            frame.setVisible(true);
            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent windowEvent) {
                    System.exit(0);
                }
            });
        });
    }

    static class MyKeyEventDispatcher implements KeyEventDispatcher {
        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            // 只处理按键按下事件,避免重复执行
            if (e.getID() != KeyEvent.KEY_PRESSED) {
                return false; // 不拦截其他事件,交给默认逻辑处理
            }

            int keyCode = e.getKeyCode();
            StringBuilder displayContent = new StringBuilder();

            // 识别组合修饰键:Ctrl/Shift/Alt
            if (e.isControlDown()) {
                displayContent.append("Ctrl+");
            }
            if (e.isShiftDown()) {
                displayContent.append("Shift+");
            }
            if (e.isAltDown()) {
                displayContent.append("Alt+");
            }

            // 自定义显示内容:区分普通字符和功能键
            if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
                // 普通字符键,显示字符和按键码
                displayContent.append(String.format("'%c' (按键码:%d)", e.getKeyChar(), keyCode));
            } else {
                // 功能键,显示按键名称和按键码
                displayContent.append(String.format("%s (按键码:%d)", KeyEvent.getKeyText(keyCode), keyCode));
            }

            // 添加到TextArea并换行
            textArea.append(displayContent.toString() + "\n");

            // 返回true表示拦截事件,不再传递给其他组件;返回false则允许事件继续流转
            return true;
        }
    }
}

核心要点说明

  1. 事件过滤:通过e.getID() == KeyEvent.KEY_PRESSED筛选出仅按键按下的事件,彻底解决重复执行问题。
  2. 组合键识别:使用isControlDown()、isShiftDown()、isAltDown()三个方法判断修饰键状态,轻松组合显示。
  3. 按键内容处理:
    • 普通字符键可以通过getKeyChar()直接获取输入字符(自动处理Shift+字母的大小写)。
    • 功能键的getKeyChar()会返回CHAR_UNDEFINED,此时用KeyEvent.getKeyText(keyCode)获取如"F1"、"LEFT"这类按键名称。
  4. 事件拦截控制:返回true会拦截事件,不让其他组件处理;如果需要保留组件默认行为,返回false即可。

内容的提问来源于stack exchange,提问作者JacTy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:31:35