26

是否有任何方法或库来获得系统范围的(全局)键盘快捷键以在 Java 应用程序中执行操作?

4

7 回答 7

17

我是 JIntellitype 的作者,我可以告诉你一个事实,这必须在 DLL 中本地完成,并像 JIntellitype 一样从 Java JNI 调用。这是一个操作系统级别的钩子,在 JDK 中没有实现,因此必须使用 JIntellitype 和 jxGrabKey 等库。据我所知,还没有人为 OSX 写过。

JIntellitype 在 Github 上是开源的,所以如果你想了解它是如何工作的,只需查看代码

于 2010-11-16T01:00:27.063 回答
13

没有,但在 Windows 中你可以使用这个:

智能型

不幸的是,对于 Linux 和 OSX,我一无所知,这可能就是为什么它没有随 java 开箱即用的原因。

如果您找到其他平台,请在此处发布 :)

只是为了好奇,你在做什么?

于 2009-01-19T19:15:21.660 回答
11

我刚刚找到https://github.com/kwhat/jnativehook

好像是跨平台的。

这是他们监听按键的示例代码:

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.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) {
            GlobalScreen.unregisterNativeHook();
        }
    }

    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());
    }
}

检查修饰符是基于位掩码(我们都应该知道但总是忘记的东西:-P):

    boolean isAltPressed = (e.getModifiers() & NativeKeyEvent.ALT_MASK) != 0;
    boolean isShiftPressed = (e.getModifiers() & NativeKeyEvent.SHIFT_MASK) != 0;

这可以与 KeyCode 结合使用:

if (e.getKeyCode() == NativeKeyEvent.VK_2 && isShiftPressed && isAltPressed){...}

这是从这里修改的示例

您还应该修改默认日志记录行为,否则它将向控制台发送垃圾邮件:

// Get the logger for "org.jnativehook" and set the level to warning.
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.WARNING);

// Don't forget to disable the parent handlers.
logger.setUseParentHandlers(false);

代码示例来自这里

于 2016-10-26T15:48:13.820 回答
2

更新:我不知道您是否可以从 JVM 外部挂钩事件。我认为 Swing/AWT 组件必须有焦点才能工作。

您需要在 Java AWT 事件队列中挂接,以绝对确保您可以获得全局(jvm 范围)按键。

采用

EventQueue ev = Toolkit.getSystemEventQueue();
// MyCustomEventQueue extends EventQueue and processes keyboard events in the dispatch
ev.push(new MyCustomEventQueue());

class MyEventQueue extends EventQueue
{
    protected void dispatchEvent(AWTEvent event)
    {
       // all AWTEvents can be indentified by type, KeyEvent, MouseEvent, etc
       // look for KeyEvents and match against you hotkeys / callbacks
    }
}

我认为可能还有其他方法可以使用动作图来完成全局按键操作。我实际上已经使用了上述方法

于 2009-01-19T19:14:36.573 回答
2

对于 Windows,您需要一个键盘挂钩 dll。您可以从 java 初始化您的 dll,这将导致它注册侦听器。你会得到你需要的。检查 msdn 是否有 dll 挂钩或键盘挂钩。其中之一应该设置你。

对于 linux,我认为这应该更容易,但我自己从未做过。

http://ubuntuforums.org/showthread.php?t=864566

Google 的“linux 监听全局按键”(无引号)的第一个结果出现了一些我认为可以帮助您适应 X11 环境的东西

OSX 可能只能使用接近此的解决方案。但最后,您可能需要为每个平台提供一个 dll,除非 JNA 可以毫无问题地做到这一点,否则最坏的情况已经过去。

于 2009-02-05T09:07:45.230 回答
1

JDIC(Java 桌面集成)可以帮助
https://jdic.dev.java.net/

对我来说似乎有点无人维护。我不知道。
如果有人知道更多,请报告!
我对这个功能也很感兴趣。

于 2009-06-13T17:59:47.340 回答
0

您现在可以使用 JNA - 请参阅https://github.com/tulskiy/jkeymaster

我已经在 Windows 10 笔记本电脑上轻松完成了这项工作——我没有在其他平台上亲自测试过——显然它也适用于 MacOS 和“基于 X11 的系统(理论上,只在一些 Linux 发行版和 PCBSD 上测试过)” .

设置起来应该不难——你需要 slf4j 让它运行。

您不需要构建 jar。

例如,此代码有效地禁用了“f”键并记录了您按下它的事实。

import com.tulskiy.keymaster.common.Provider;
import com.tulskiy.keymaster.common.HotKeyListener;
import com.tulskiy.keymaster.common.HotKey;
import javax.swing.*;

// ...          

Provider provider = Provider.getCurrentProvider(false); 
    provider.register(KeyStroke.getKeyStroke("F"), new HotKeyListener() {
            public void onHotKey(HotKey hotKey) {
                System.out.println(hotKey);
            }
        });

我希望这可以帮助别人

于 2020-07-14T16:09:04.930 回答