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

如何让Java将输出发送至当前焦点窗口(如打开的文本文档)

按键置换后回写文本文档的实现方案

核心思路

既然已经能通过NativeKeyListener监听全局按键,要实现置换内容回写文本文档,核心是拦截原按键输入,再通过系统级按键模拟,把置换后的内容输入到当前激活的文本文档中。直接修改文本文档的本地文件会和编辑器缓存冲突,实时模拟键盘输入是最可靠的方式。

具体步骤与代码实现

1. 拦截原生按键事件

在nativeKeyPressed方法中调用event.consume(),阻止原按键被系统处理,这样原始输入就不会出现在文本文档里。同时区分普通字符键和功能键(回车、退格等),分别处理。

2. 实现凯撒密码置换逻辑

将监听得到的按键文本转换成字符,按凯撒密码规则完成置换,注意处理大小写和非字母字符的边界情况。

3. 用Robot类模拟键盘输入

Java的java.awt.Robot类可以模拟系统级按键事件,把置换后的字符转换成对应的按键动作发送给系统,实现内容回写。

完整示例代码

import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;
import java.awt.*;
import java.awt.event.KeyEvent;

public class KeyInterceptor implements NativeKeyListener {
    private Robot robot;
    private final int caesarShift = 3; // 凯撒密码位移量

    public KeyInterceptor() {
        try {
            robot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void nativeKeyPressed(NativeKeyEvent e) {
        // 拦截原按键,阻止系统处理
        e.consume();

        String keyText = NativeKeyEvent.getKeyText(e.getKeyCode());
        // 处理单字符按键
        if (keyText.length() == 1) {
            char originalChar = keyText.charAt(0);
            char replacedChar = caesarReplace(originalChar);
            simulateKeyPress(replacedChar);
        } else {
            // 处理功能键,直接模拟原按键
            simulateFunctionKey(e.getKeyCode());
        }
    }

    // 凯撒密码置换逻辑
    private char caesarReplace(char c) {
        if (Character.isLowerCase(c)) {
            return (char) ((c - 'a' + caesarShift) % 26 + 'a');
        } else if (Character.isUpperCase(c)) {
            return (char) ((c - 'A' + caesarShift) % 26 + 'A');
        }
        // 非字母字符直接返回
        return c;
    }

    // 模拟普通字符按键
    private void simulateKeyPress(char c) {
        int keyCode = KeyEvent.getExtendedKeyCodeForChar(c);
        if (keyCode != KeyEvent.VK_UNDEFINED) {
            // 大写字母需要按住Shift键
            if (Character.isUpperCase(c)) {
                robot.keyPress(KeyEvent.VK_SHIFT);
            }
            robot.keyPress(keyCode);
            robot.keyRelease(keyCode);
            if (Character.isUpperCase(c)) {
                robot.keyRelease(KeyEvent.VK_SHIFT);
            }
        }
    }

    // 模拟功能键(回车、退格等)
    private void simulateFunctionKey(int nativeKeyCode) {
        int awtKeyCode = mapNativeKeyToAwt(nativeKeyCode);
        if (awtKeyCode != -1) {
            robot.keyPress(awtKeyCode);
            robot.keyRelease(awtKeyCode);
        }
    }

    // JNativeHook键码与AWT键码映射
    private int mapNativeKeyToAwt(int nativeKeyCode) {
        return switch (nativeKeyCode) {
            case NativeKeyEvent.VC_ENTER -> KeyEvent.VK_ENTER;
            case NativeKeyEvent.VC_BACKSPACE -> KeyEvent.VK_BACK_SPACE;
            case NativeKeyEvent.VC_TAB -> KeyEvent.VK_TAB;
            case NativeKeyEvent.VC_SPACE -> KeyEvent.VK_SPACE;
            // 可根据需求添加更多功能键映射
            default -> -1;
        };
    }

    @Override
    public void nativeKeyReleased(NativeKeyEvent e) {}

    @Override
    public void nativeKeyTyped(NativeKeyEvent e) {}
}

主程序初始化代码

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;

public class Main {
    public static void main(String[] args) {
        try {
            GlobalScreen.registerNativeHook();
        } catch (NativeHookException ex) {
            System.err.println("无法注册原生钩子");
            System.err.println(ex.getMessage());
            System.exit(1);
        }
        // 添加自定义按键监听器
        GlobalScreen.addNativeKeyListener(new KeyInterceptor());
    }
}

注意事项

  • 权限要求:Windows、macOS、Linux系统均需给程序授予「辅助功能」或「输入监控」权限,否则Robot类无法模拟按键。
  • 字符映射:特殊字符(如中文、符号)的键码映射需要额外适配,可通过KeyEvent类的常量逐一对应。
  • 性能优化:高频按键场景下,可添加事件队列缓冲,避免Robot模拟出现延迟或丢包。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 05:46:38