一般购物网站项目深圳做网站比较好天涯
这里使用的是一位大佬写的项目jkeymaster,对其进行了一些拓展,支持windows、Linux、MacOS下的快捷键冲突检测、事件注册。
https://mvnrepository.com/artifact/com.github.tulskiy/jkeymaster
1、添加依赖
<dependency><groupId>com.github.tulskiy</groupId><artifactId>jkeymaster</artifactId><version>1.3</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-jdk14</artifactId><version>1.7.13</version></dependency>
2、由于原来的方法,在热键冲突时,会打印WARNING日志,日志的错误信息可以自己手动处理,认为是发生了冲突,由于原来的项目是异步执行的,所有主线程是无法获得异常信息的,这里需要对异常信息做一下拦截处理,新增以下代码。
自定义异常类HotkeyRegistrationException:
package com.comleader.evaluation.util.hotkey;/*** 热键注册异常(包含错误码)*/
public class HotkeyRegistrationException extends RuntimeException {private final int errorCode;public HotkeyRegistrationException(int errorCode, String message) {super(message);this.errorCode = errorCode;}// 静态工厂方法:快速创建异常public static HotkeyRegistrationException of(int errorCode, String message) {return new HotkeyRegistrationException(errorCode, message);}// 常用异常快捷抛出方法public static void throwConflict(String message) {throw new HotkeyRegistrationException(ERR_HOTKEY_IN_USE, message);}public static void throwInvalidFormat(String message) {throw new HotkeyRegistrationException(ERR_INVALID_HOTKEY_FORMAT, message);}public static void throwOtherError(String message) {throw new HotkeyRegistrationException(ERR_UNKNOWN, message);}// Getterpublic int getErrorCode() {return errorCode;}// 错误码常量(精简核心错误码)public static final int ERR_HOTKEY_IN_USE = 2001; // 热键已被占用public static final int ERR_INVALID_HOTKEY_FORMAT = 2002; // 热键格式无效public static final int ERR_UNKNOWN = 2099; // 未知错误
}
自定义的异常处理器:HotkeyErrorHandler
package com.comleader.evaluation.util.hotkey;import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;/*** 拦截热键注册相关日志,转换为异常并通过回调传递*/
public class HotkeyErrorHandler extends Handler {private final HotkeyErrorCallback errorCallback; // 回调接口(传递异常给调用方)public HotkeyErrorHandler(HotkeyErrorCallback errorCallback) {this.errorCallback = errorCallback;setLevel(Level.WARNING); // 只处理警告及以上级别日志// 监听热键相关日志(X11/Windows提供者)java.util.logging.Logger logger = java.util.logging.Logger.getLogger("com.tulskiy.keymaster");logger.addHandler(this);}@Overridepublic void publish(LogRecord record) {if (record.getLevel() == Level.WARNING) {String loggerName = record.getLoggerName();String message = record.getMessage();try {handleError(loggerName, message); // 解析错误并抛出异常} catch (HotkeyRegistrationException e) {// 触发回调,将异常传递给调用方if (errorCallback != null) {errorCallback.onError(e);}}}}/*** 解析日志信息,判断错误类型并抛对应异常*/private void handleError(String loggerName, String message) {// 热键冲突(Windows/X11通用)if (message.contains("Could not register hotkey") || message.contains("BadIDChoice")) {HotkeyRegistrationException.throwConflict(message);}// 无效格式else if (message.contains("invalid hotkey format")) {HotkeyRegistrationException.throwInvalidFormat(message);}// 其他错误else if (message.toLowerCase().contains("error") || message.toLowerCase().contains("fail")) {HotkeyRegistrationException.throwOtherError(message);}}// 无需实现复杂逻辑,空实现即可@Overridepublic void flush() {}@Overridepublic void close() throws SecurityException {}/*** 错误回调接口:将异常传递给调用方*/@FunctionalInterfacepublic interface HotkeyErrorCallback {void onError(HotkeyRegistrationException e);}
}
测试的main方法,这里这样处理是因为注册事件是异步的,无法获取到注册冲突信息,所以需要强制同步等待结果:
package com.comleader.evaluation.util;import com.comleader.evaluation.util.hotkey.HotkeyErrorHandler;
import com.comleader.evaluation.util.hotkey.HotkeyRegistrationException;
import com.tulskiy.keymaster.common.HotKeyListener;
import com.tulskiy.keymaster.common.Provider;import javax.swing.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;public class Test2 {public static void main(String[] args) {int result = registerHotkey("alt A");switch (result) {case 0:System.out.println("热键注册成功");break;case 1:System.out.println("热键注册失败:已被其他程序占用");break;case -1:System.out.println("热键注册失败:无效的热键格式");break;default:System.out.println("热键注册失败:未知错误(错误码:" + result + ")");}}/*** 注册热键并返回结果码* @param hotKeyStr 热键字符串(如"ctrl alt A")* @return 0=成功,1=冲突,-1=无效格式,-2=其他错误*/public static int registerHotkey(String hotKeyStr) {CountDownLatch latch = new CountDownLatch(1); // 同步等待回调int[] result = {0}; // 存储结果码(0=默认成功)// 初始化热键提供者(静态初始化并启动)Provider provider = Provider.getCurrentProvider(false);try {// 1. 解析热键格式(失败直接返回-1)KeyStroke keyStroke = KeyStroke.getKeyStroke(hotKeyStr);if (keyStroke == null) {return -1;}// 2. 注册错误回调:收到异常时设置结果码HotkeyErrorHandler errorHandler = new HotkeyErrorHandler(e -> {if (e.getErrorCode() == HotkeyRegistrationException.ERR_HOTKEY_IN_USE) {result[0] = 1; // 冲突} else {result[0] = -2; // 其他错误}latch.countDown(); // 通知等待线程});// 3. 注册热键HotKeyListener listener = hotKey -> System.out.println("热键触发:" + hotKey);provider.register(keyStroke, listener);// 4. 等待1秒(确保回调有足够时间处理)if (!latch.await(1, TimeUnit.SECONDS)) {result[0] = 0; // 超时未出错,视为成功}} catch (Exception e) {result[0] = -2; // 其他异常(如服务未启动)}return result[0];}
}
可以根据代码自行拓展和修改。
