Java 监听 Mac 键盘输入实现快捷键功能

菠萝🍍的博客 有谁不喜欢吃菠萝呢 本文由博客端 https://www.runnable.run 主动推送

背景需求

当你想使用 Java 给 Mac 上注册快捷键时,你百度到可以通过 jnativehook 进行实现。然后你发现,下载下来的例子进行运行不了,这篇文章说的就是怎么解决这个问题,以及如果通过这个 jnativehook 实现 Mac 上的系统级快捷键。

jnativehook

JNativeHook 为 Java 程序提供全局的键盘和鼠标事件侦听功能。你可以来处理程序外的键盘输入和鼠标动作。当然 JNativeHook 使用了 JNI 技术调用了系统的方法来实现该功能。

github 地址: https://github.com/kwhat/jnativehook

引用正确的 dependency

如果你是在 maven 仓库中进行搜索的话,你会发现它有好几个来源
image.png

此时,不应该点开第一个,因为当你使用第一个的时候就会导致之后的 Simple Code 都执行不了。

正确的应该是选择最新更新 2021 年的那个,也就是它

image.png

简单例子

jnativehook 的 github readme.md 页面上其实提到了一个很实用的例子,可以满足绝大多数的需求了。

image.png

OK,此时你新建了一个 Maven 项目,然后引入了刚刚说到的最新的 dependency,我想是没错的。

然后当你复制这个 Demo 进行启动 main 方法的时候,第一次执行 mac 会弹出提示说,给予 Applicaiton 权限。

类似以下画面,授予权限就行

image.png

程序的成功执行页面是这样的。每当你在触控板上进行移动,键盘输出内容,都会进行输出,这样就体现了这个工具的强大性,可以实时的监听你的操作。

image.png

注册全局快捷键

ok,完成以上内容之后,现在我们该说说代码了。在使用的过程中 jnativehook 似乎没有具体对于快捷键的实现,也就是这一部分需要我们进行完成。

当然在完成上面那个小 demo 之后我猜你也应该猜到怎么做了,既然我们能监听到 mac 的所有输入了,那假如连续输入对应的键然后触发相应的功能就是实现了快捷键的功能。

ok,来一个小功能先,就是知道怎么只监听所有的键盘输入

Simple: https://github.com/kwhat/jnativehook/blob/2.2/doc/Keyboard.md

import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.NativeHookException;
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;

public class GlobalKeyListenerExample implements NativeKeyListener {
	public void nativeKeyPressed(NativeKeyEvent e) {
		System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));

		if (e.getKeyCode() == NativeKeyEvent.VC_ESCAPE) {
            		try {
                		GlobalScreen.unregisterNativeHook();
            		} catch (NativeHookException nativeHookException) {
                		nativeHookException.printStackTrace();
            		}
        	}
	}

	public void nativeKeyReleased(NativeKeyEvent e) {
		System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
	}

	public void nativeKeyTyped(NativeKeyEvent e) {
		System.out.println("Key Typed: " + e.getKeyText(e.getKeyCode()));
	}

	public static void main(String[] args) {
		try {
			GlobalScreen.registerNativeHook();
		}
		catch (NativeHookException ex) {
			System.err.println("There was a problem registering the native hook.");
			System.err.println(ex.getMessage());

			System.exit(1);
		}

		GlobalScreen.addNativeKeyListener(new GlobalKeyListenerExample());
	}
}

上面实现的功能就是,键盘的任何输入都会进行输出打印。

那么下一步,就是对当中的方法 nativeKeyPressed 进行一下改造,这里做一个简单的实现,假设现在我的想要实现的快捷键是: Ctrl + Command + P 进行触发功能

那么对当中的方法 nativeKeyPressed 进行改造

    protected final static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue();

    public void nativeKeyPressed(NativeKeyEvent e) {
        //当有键盘输入的时候,放入队列
        try {
            queue.put(e.getKeyCode());
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

        // Ctrl + command + p
        int[] hotKeyArray = {NativeKeyEvent.VC_CONTROL, NativeKeyEvent.VC_META, NativeKeyEvent.VC_P};
        //如果队列中的数据大于等于3,那就进行判断是不是包含连续且等于我们指定的键的顺序
        //如果存在就进行执行处罚
        if (queue.size() >= 3 && judgeCombinationKey(hotKeyArray)){
            try {
                do something.........
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            queue.clear();
        }
        if (queue.size() == 4){
            queue.poll();
        }
    }
  
    protected Boolean judgeCombinationKey(int[] hotKeyArray){
        Object[] queueKey = queue.toArray();

        Predicate<int[]> keyArrayPredicateOne = hotKeies -> (int)queueKey[0] == hotKeies[0]
                && (int)queueKey[1] == hotKeies[1]
                && (int)queueKey[2] == hotKeies[2];

        Predicate<int[]> keyArrayPredicateTwo = hotKeies -> (int)queueKey[1] == hotKeies[0]
                && (int)queueKey[2] == hotKeies[1]
                && (int)queueKey[3] == hotKeies[2];

        return queue.size() == 3 ? keyArrayPredicateOne.test(hotKeyArray) :
                keyArrayPredicateOne.or(keyArrayPredicateTwo).test(hotKeyArray);

    }

好了,当完成以上的内容其实就已经完成了!

  • JNativeHook
    1 引用
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    2990 引用 • 8141 回帖 • 593 关注
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    149 引用 • 585 回帖 • 1 关注

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...