java监听全局组合键
1. jintellitype
- pom
<!-- 不能注册多个组合键比如alt+abc --> <!-- https://mvnrepository.com/artifact/com.melloware/jintellitype --> <dependency> <groupId>com.melloware</groupId> <artifactId>jintellitype</artifactId> <version>1.4.1</version> </dependency>
- 代码
package com.hotkey.app; import cn.hutool.core.date.DateUtil; import com.melloware.jintellitype.JIntellitype; public class IntelApplication { public static void main(String[] args) { // 添加全局热键 JIntellitype instance = JIntellitype.getInstance(); instance.registerHotKey(0, JIntellitype.MOD_ALT + JIntellitype.MOD_SHIFT, 'B'); instance.registerHotKey(2, 20, 'B'); instance.registerHotKey(1, "CTRL+SHIFT+X+V"); instance.registerHotKey(3, "CTRL+SHIFT+ALT+WIN+DELETE+B"); // 添加热键监听器 instance.addHotKeyListener(hotkey -> { System.out.println(DateUtil.now() + " Hotkey pressed: " + hotkey); // 在这里处理你的逻辑 }); } }
- 缺点: 对于ctrl a b 按ctrl b也可以触发
2. jkeymaster
- pom
<!-- https://mvnrepository.com/artifact/com.github.tulskiy/jkeymaster --> <dependency> <groupId>com.github.tulskiy</groupId> <artifactId>jkeymaster</artifactId> <version>1.3</version> </dependency> <!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna --> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.12.1</version> </dependency>
- 代码
import com.tulskiy.keymaster.common.Provider; import javax.swing.*; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; public class KeyApplication { public static void main(String[] args) { Provider provider = Provider.getCurrentProvider(true); provider.register( KeyStroke.getKeyStroke(KeyEvent.CTRL_MASK, InputEvent.ALT_MASK), x -> System.err.println(x)); } }
- 缺点: 对于+ = [ ]特殊按键识别不到; 不能注册类似ctrl a b会报错
3. jnativehook(推荐)
- pom
<!-- https://mvnrepository.com/artifact/com.1stleg/jnativehook --> <dependency> <groupId>com.1stleg</groupId> <artifactId>jnativehook</artifactId> <version>2.1.0</version> </dependency>
- 代码: https://gitee.com/codorld/hotkey-app
- 补充
- 代码中防止程序再次启动使用的方法是端口占用, 但是测试过程中经常遇到各种问题, 导致启动两次, 可以使用文件锁来实现, 如果可以尽量使用绝对路径
/** * 通过.hotkey.lock的锁来判断是否有程序启动过 * 去掉RandomAccessFile的放入try警告, 放进去执行完会自动释放 * * @return true启动过, 不可再次启动, 反之false */ @SuppressWarnings("all") private static boolean isAppAlreadyRunning() { try { File lockFile = new File(System.getenv("APPDATA") + "\\hotkey\\.hotkey.lock"); if (!lockFile.getParentFile().exists()) { lockFile.getParentFile().mkdirs(); } RandomAccessFile file = new RandomAccessFile(lockFile, "rw"); FileChannel channel = file.getChannel(); FileLock lock = channel.tryLock(); return lock == null; // 如果锁获取失败,说明已经有实例在运行 } catch (Exception e) { ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); e.printStackTrace(new PrintStream(baoStream)); log.error(baoStream.toString()); return false; // 处理异常情况,也可以选择抛出异常 } }
- 代码中保存单次控制台日志的方法, 在任务计划中行不通, 通过批处理会有命令行弹窗, 体验不好
- 可以考虑vsb文件, 无窗口方式运行
- 或者将堆栈信息写入日志文件
ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); e.printStackTrace(new PrintStream(baoStream)); log.error(baoStream.toString());
- 代码中防止程序再次启动使用的方法是端口占用, 但是测试过程中经常遇到各种问题, 导致启动两次, 可以使用文件锁来实现, 如果可以尽量使用绝对路径