2015-08-18 66 views
2

我正在做一個在Javafx中有gui的翻譯程序。我正在使用JNativeHook爲應用程序未聚焦時啓用全局keylisteners。當alt和t被同時按下時,程序應該從任務欄恢復自己。如何將JNativeHook連接到JavaFX線程?

但是,當我按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,它基本上是添加一個keylistener到你的java程序,當它沒有被關注和使用時其他東西在你的電腦上。

有沒有什麼辦法可以讓JNativeHook線程訪問我的javafx線程,在最小化之後用熱鍵重新打開程序?

回答

3

只是包裝他們Platform.runLater,使他們在FX的線程上運行,即:

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

     check(); 
    }); 
+2

Platform.runlater是所有JavaFX的答案^^ –

+0

非常感謝! – Josh

+1

Platform.runLater是任何問題的解決方案。 Platform.runLater是未來。 –

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