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>
  • 代码
    import cn.hutool.core.collection.CollUtil;
    import org.jnativehook.GlobalScreen;
    import org.jnativehook.NativeHookException;
    import org.jnativehook.keyboard.NativeKeyEvent;
    import org.jnativehook.keyboard.NativeKeyListener; import javax.swing.*;
    import java.awt.*;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.logging.Level;
    import java.util.logging.Logger; /**
    * 监听键盘和鼠标按键, 这个是强制顺序和不支持重复的
    * 如果要支持重复就得使用List保存快捷键, 并给每个编键去配置标志位, 或者快捷键数组使用对象数组
    * 如果要不要求顺序, 就按下时候直接标志位变成true即可
    *
    * @author codor
    * @date 2023/12/08 16:23
    * @see org.jnativehook.example.NativeHookDemo
    */
    public class NativeApplication extends JFrame implements NativeKeyListener { // ----------------------------------------------------------------------------------------------------------------- 逻辑使用 /**
    * 快捷键组合
    * 名字也可以不写上去, 使用NativeKeyEvent.getKeyText(event.getKeyCode())获取
    */
    private Map<Integer, String> hotKeys; /**
    * 键编码的列表, 因为要保证顺序
    */
    private List<Integer> codes; /**
    * 快捷键是否按下标标志位
    */
    private Map<Integer, Boolean> flags; /**
    * 窗口是否展示出来了
    */
    private boolean isWindowShow = false; // ---------------------------------------------------------------------------------------------------------------- 界面使用 /**
    * 倒计时
    */
    private Timer countdownTimer; /**
    * 倒计时事件
    */
    private final static Integer COUNT_DOWN_SECONDS = 10; /**
    * 初始化标志位
    *
    * @see org.jnativehook.keyboard.NativeKeyEvent
    */
    public void initHotKeys() {
    this.hotKeys = new LinkedHashMap<>();
    this.hotKeys.put(29, "Ctrl");
    this.hotKeys.put(46, "C");
    this.hotKeys.put(45, "X");
    this.hotKeys.put(47, "V"); // 初始化键编码
    this.codes = new ArrayList<>();
    this.hotKeys.forEach((k, v) -> this.codes.add(k)); // 初始化标指位
    this.initFlags();
    } /**
    * 初始化标志位
    */
    public void initFlags() {
    if (this.hotKeys == null) {
    this.initHotKeys();
    }
    this.flags = new HashMap<>();
    for (Integer code : this.codes) {
    this.flags.put(code, false);
    }
    } /**
    * 按下键时候, 强制要求顺序
    *
    * @param code 键编码
    * @return 是否全部按下了, true是, 反之false
    */
    public boolean pressedKey(int code) {
    // 如果未在内, 重置标志位
    if (!this.codes.contains(code)) {
    this.initFlags();
    return false;
    } for (Integer k : this.codes) {
    // 循环到 第一个非按下状态的就跳出循环或退出方法
    if (!this.flags.get(k)) {
    // 并且等于按下的键, 设置按下成功
    if (k.equals(code)) {
    this.flags.put(code, true);
    break;
    } else { // 不是不等于按下的, 说明按了后面的,
    this.initFlags();
    return false;
    }
    }
    } // 只有break时候到这里, 判断是否循环完, 也即code是否最后一个
    return code == this.codes.get(this.codes.size() - 1);
    } /**
    * 松开键
    */
    public void releaseKey(int code) {
    this.flags.put(code, false);
    } public String getKeyTexts() {
    if (CollUtil.isEmpty(this.codes)) {
    return "";
    }
    StringBuilder resB = new StringBuilder(" ");
    for (Integer code : this.codes) {
    resB.append(NativeKeyEvent.getKeyText(code)).append(" ");
    }
    return resB.toString();
    } public void showWindow(String hotKeyTexts) { setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    setUndecorated(true); // 窗口无装饰, 但是标题也会干掉 setTitle("倒计时窗口");
    setLayout(new BorderLayout()); JLabel countdownLabel = new JLabel("倒计时: " + COUNT_DOWN_SECONDS + " 秒", JLabel.CENTER);
    JButton cancelButton = new JButton("取消"); cancelButton.addActionListener(e -> {
    // 点击取消按钮时的处理
    if (countdownTimer != null) {
    // 重置标志位
    this.initFlags();
    // 关闭窗口
    this.closeWindow();
    }
    }); add(countdownLabel, BorderLayout.CENTER);
    add(cancelButton, BorderLayout.SOUTH); setSize(300, 150);
    setLocationRelativeTo(null); // 将窗口置于屏幕中央
    setVisible(true); AtomicInteger second = new AtomicInteger(COUNT_DOWN_SECONDS);
    countdownTimer = new Timer(1000, e -> {
    second.getAndDecrement(); if (second.get() >= 0) {
    countdownLabel.setText("倒计时: " + second.get() + " 秒");
    } else {
    // 关闭窗口
    this.closeWindow();
    // 触发成功后发送指令
    // 指令发送成功后重置标志位
    this.initFlags();
    }
    }); countdownTimer.start();
    } public void closeWindow() {
    countdownTimer.stop();
    dispose(); // 关闭窗口
    setVisible(false); // 设置窗口不可见
    getContentPane().removeAll(); // 移除所有组件
    revalidate(); // 重新验证布局
    repaint(); // 重绘窗口 // 关闭窗口时候重置
    isWindowShow = false;
    } // ---------------------------------------------------------------------------------------------------------------- Override Method @Override
    public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) {
    } @Override
    public void nativeKeyPressed(NativeKeyEvent event) {
    boolean isHotKey = this.pressedKey(event.getKeyCode());
    // 成功并且窗口未展示时候
    if (isHotKey && !isWindowShow) {
    System.err.println("触发快捷组合键成功...");
    // 窗口标志位设置成功
    isWindowShow = true;
    this.showWindow(this.getKeyTexts());
    }
    } @Override
    public void nativeKeyReleased(NativeKeyEvent event) {
    this.releaseKey(event.getKeyCode());
    } public static void main(String[] args) {
    try {
    // 设置日志级别,避免 JNativeHook 的日志输出
    Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
    logger.setLevel(Level.OFF); // 注册全局键盘事件
    GlobalScreen.registerNativeHook();
    } catch (NativeHookException ex) {
    ex.printStackTrace();
    System.err.println("Failed to initialize native hook. Exiting.");
    System.exit(1);
    } // 添加 NativeKeyListener
    NativeApplication application = new NativeApplication();
    application.initFlags();
    GlobalScreen.addNativeKeyListener(application);
    }
    }

java监听全局组合键的更多相关文章

  1. JS实现键盘监听(包括组合键)

    依然使用案例驱动~案例是学习的最好实践!   <html>   <head>   <meta http-equiv="Content-Type" co ...

  2. vue 定义全局函数,监听android返回键事件

    vue 定义全局函数,监听android返回键事件 方法一:main.js 注入(1)在main.js中写入函数Vue.prototype.changeData = function (){ aler ...

  3. vue+hbuilder监听安卓返回键问题

    1.监听安卓返回键问题 效果:在一级页面按一下返回键提示退出应用,按两下退出应用;在其它页面中,按一下返回上个历史页面 1 2 import mui from './assets/js/mui.min ...

  4. 监听 手机back键和顶部的回退

    // 回退事件,监听 手机back键和顶部的回退 pushHistory(); window.addEventListener("popstate", function(e) { ...

  5. Java监听模式

    说明 生活中,监听无处不在.比如说,手机播放音乐功能,也是一种监听:你不点击播放按钮,手机就不放歌,当你点击时,手机就播放音乐.即触发某种行为,便执行相应的动作. 组成 Java监听模式右三个部分组成 ...

  6. java 监听控制台输入

    分享一下我写的java监听控制台输入并可以给出响应的功能. 很多时候需要监听控制台的输入内容,相当于信号监听,根据输入的内容做出相应的动作,这里给出我的一个简单实现. 要注意的是:监听得到的消息中前后 ...

  7. javascript监听手机返回键

    javascript监听手机返回键 <pre> if (window.history && window.history.pushState) { $(window).on ...

  8. Vue 监听鼠标左键 鼠标右键以及鼠标中键修饰符click.left&contextmenu&click.middle

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. iOS 监听 出发 Home键 NSNotificationCenter UIApplicationWillResignActiveNotification

    第一步: 创建2个NSNotificationCenter监听 [[NSNotificationCenter defaultCenter] addObserver:self selector:@sel ...

  10. java监听事件

    2014年2月23日 09:51:54 成功添加了打开官网的事件, 回头研究下,那个打开url的类 java的System.getProperty()方法可以获取的值 ################ ...

随机推荐

  1. 让 GPT-4 来修复 Golang “数据竞争”问题(续) - 每天5分钟玩转 GPT 编程系列(7)

    目录 1. 我以为 2. 阴魂不散的"数据竞争"问题 3. 老规矩,关门放 GPT-4 3.1 复现问题 3.2 让 GPT-4 写一个单元测试 3.3 修复 Wait() 中的逻 ...

  2. .Net AsyncLocal介绍

    AsyncLocal的基本概念 AsyncLocal是一个在异步环境中存储和传递状态的类型.它允许你在线程或任务之间共享数据,而不会受到异步上下文切换的影响. 每一个异步的AsyncLocal的数据都 ...

  3. Python 基础面试第四弹

    1. Python中常用的库有哪些,作用分别是什么 requests: requests 是一个用于发送 HTTP 请求的库,它提供了简单而优雅的 API,可以轻松地发送 GET.POST.PUT.D ...

  4. 一个 Java 接口快速开发框架:magic-api

    一.简介 magic-api是一个基于Java的接口快速开发框架,编写接口将通过magic-api提供的UI界面完成,自动映射为HTTP接口.无需定义Controller.Service.Dao.Ma ...

  5. ELK环境部署-基础环境安装(一)

    ELK简介 ElasticSearch工作原理以及专用名词 ELK是Elasticsearch(ES) , Logstash, Kibana的结合,是一个开源日志收集软件. Elasticsearch ...

  6. 云原生 | 企业内使用 CoreDNS 构建高性能、插件化的DNS服务器

    [点击 关注「 全栈工程师修炼指南」公众号 ] 设为「️ 星标」带你从基础入门 到 全栈实践 再到 放弃学习! 涉及 网络安全运维.应用开发.物联网IOT.学习路径 .个人感悟 等知识分享. 希望各位 ...

  7. 避坑|在读取excel.xlsx文件中的内容时发现明明只有3行,但跑起来却认为有13行,导致有10行None,UI自动化测试代码空跑了10次;|UI自动化测试|数据驱动

    在读取excel.xlsx文件中的内容时发现明明只有3行,但跑起来却认为有13行,导致有10行None,UI自动化测试代码空跑了10次: 原因:excel.xlsx内容清除时用delete快捷键导致, ...

  8. Andrew Ng 机器学习&深度学习课程 代码作业解答 集合

    写在最前 ​ 2018年是对自己来说是崭新的一年,在过去的3个多月里,从最基础的lr, 学到现在的LSTM, GAN..感觉第一次追上了计算机科学飞速发展的浪潮.虽然很多地方都仍是一知半解,但时间还长 ...

  9. 关于Unity 如何与Blazor Server结合

    关于Unity 如何与Blazor Server结合 一.介绍 最近工作中有`Unity`与`Blazor Server`结合的需求,在网上找了一圈,发现这方面的资料比较少,特此写下这篇记录一下自己的 ...

  10. Solution Set -「ARC 111」

    「ARC 111A」Simple Math 2 Link. \(\lfloor \frac{10^N - kM^2}{M} \rfloor \equiv \lfloor \frac{10^N}{M} ...