如何将JNativeHook连接到JavaFX Thread?

时间:2015-08-18 03:51:20

标签: java multithreading javafx

我正在制作一个在Javafx中有gui的翻译程序。我正在使用JNativeHook来启用应用程序不在焦点时的全局键控系统。当同时按下alt和t时,程序应该从任务栏恢复自身。

但是,当我按下alt和t时,会出现错误,说JNativeHook线程无法使用javafx线程运行。

甚至可以让GlobalScreen线程与javafx线程通信吗?

这是我的全局keylistener代码

GlobalScreen.addNativeKeyListener(listener);

这是我的倾听者

                @Override
                public void nativeKeyPressed(NativeKeyEvent nativeKeyEvent) {
                    if(nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_ALT_L){
                        alt = true;
                    }
                    if(nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_T){
                        t = true;
                    }

                    check();

                }

                @Override
                public void nativeKeyReleased(NativeKeyEvent nativeKeyEvent) {
                    if(nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_ALT_L){
                        alt = false;
                    }
                    if(nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_T){
                        t = false;
                    }
                }

                @Override
                public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) {

                }
            });

我得到的错误是

Exception in thread "JNativeHook Dispatch Thread" java.lang.IllegalStateException: Not on FX application thread; currentThread = JNativeHook Dispatch Thread
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204)

如果你不熟悉GlobalScreen,它基本上是在你的java程序没有关注并在你的计算机上使用其他东西时为你的java程序添加一个keylistener。

有什么办法可以让JNativeHook线程访问我的javafx线程,在最小化后用热键重新打开程序?

2 个答案:

答案 0 :(得分:3)

将它们包装在Platform.runLater中,使它们在FX线程上运行,即:

    Platform.runLater( () -> {
        if(nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_ALT_L){
            alt = true;
        }
        if(nativeKeyEvent.getKeyCode() == NativeKeyEvent.VC_T){
            t = true;
        }

        check();
    } );

答案 1 :(得分:0)

查看working-with-swingSwingDispatchService.java课程。您应该能够为JavaFX实现类似的功能。

public class PlatformDispatchService extends AbstractExecutorService {
    private boolean running = false;

    public SwingDispatchService() {
        running = true;
    }

    public void shutdown() {
        running = false;
    }

    public List<Runnable> shutdownNow() {
        running = false;
        return new ArrayList<Runnable>(0);
    }

    public boolean isShutdown() {
        return !running;
    }

    public boolean isTerminated() {
        return !running;
    }

    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
        return true;
    }

    public void execute(Runnable r) {
        Platform.runLater(r);
    }
}