背景需求
当你想使用 Java 给 Mac 上注册快捷键时,你百度到可以通过 jnativehook
进行实现。然后你发现,下载下来的例子进行运行不了,这篇文章说的就是怎么解决这个问题,以及如果通过这个 jnativehook
实现 Mac 上的系统级快捷键。
jnativehook
JNativeHook 为 Java 程序提供全局的键盘和鼠标事件侦听功能。你可以来处理程序外的键盘输入和鼠标动作。当然 JNativeHook 使用了 JNI 技术调用了系统的方法来实现该功能。
github 地址: https://github.com/kwhat/jnativehook
引用正确的 dependency
如果你是在 maven 仓库中进行搜索的话,你会发现它有好几个来源
此时,不应该点开第一个,因为当你使用第一个的时候就会导致之后的 Simple Code 都执行不了。
正确的应该是选择最新更新 2021 年的那个,也就是它
简单例子
在 jnativehook
的 github readme.md 页面上其实提到了一个很实用的例子,可以满足绝大多数的需求了。
OK,此时你新建了一个 Maven 项目,然后引入了刚刚说到的最新的 dependency,我想是没错的。
然后当你复制这个 Demo 进行启动 main 方法的时候,第一次执行 mac 会弹出提示说,给予 Applicaiton 权限。
类似以下画面,授予权限就行
程序的成功执行页面是这样的。每当你在触控板上进行移动,键盘输出内容,都会进行输出,这样就体现了这个工具的强大性,可以实时的监听你的操作。
注册全局快捷键
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);
}
好了,当完成以上的内容其实就已经完成了!
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于