2017-10-11 5 views
0

私はJavaFX 8アプリケーションを持っています。これは、イベントに反応するオブザーバーパターンの種類を使用しています。ライブラリによって開始されたスレッドからJavaFXコントロールを更新します。

public class EventBus { 

    public static final EventBus INSTANCE = new EventBus(); 

    private final Set<EventListener> listeners; 

    private EventBus() { 
     listeners = new HashSet<>(); 
    } 

    public void register(EventListener listener) { 
     listeners.add(listener); 
    } 

    public void fire(Event event) { 
     listeners.forEach(listener -> listener.eventFired(event)); 
    } 
} 

それはすべて私のユースケースのために、これまで非常にうまく働いた:ボタン私が観察した外部コントローラから

  • イベント、と

    • 相互作用をPlatform.runLater()開始スレッド
    • など

    今、私は電子を開始したいですHTTPサーバーをアンダーフローし、内部にJAX-RSエンドポイントをデプロイします。リクエストがそこに来るたびに、上記のイベントバスを使用してそのエンドポイント内からイベントを発生させたいと思います。だから、これは私がアンダートウ開始し、私のJAX-RSアプリケーションを展開する方法である:

    UndertowJaxrsServer server = new UndertowJaxrsServer().start(); 
    server.deploy(new MyEndpoint(eventBus)); 
    

    事がnew UndertowJaxrsServer().start()が非同期呼び出しであり、それは自分自身のスレッドを開始していることです。そして、MyEndpointがリクエストを処理してイベントを発生させようとすると、Undertowによって開始されたそのスレッドから発生します。

    ので、イベントリスナーで、私はUI上の任意の更新を行うにしようと、私が手:

    java.lang.IllegalStateException: Not on FX application thread; currentThread = XNIO-1 task-1 
        at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:236) 
        at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423) 
        at javafx.scene.Parent$2.onProposedChange(Parent.java:367) 
        at com.sun.javafx.collections.VetoableListDecorator.clear(VetoableListDecorator.java:294) 
        at ui.DialogManager.showDialog(DialogManager.java:109) 
    

    最後に、私の質問は、明示的にコードの一部を実行するためのJavaFXを指示するが方法ですコールスタックが別のもの(私は制御を持たず、私が行うことができないPlatform.runLater())からのものであっても、UIスレッド内で呼び出すことができます。

    ありがとうございます!

  • 答えて

    2

    MyEndpointがあなたのクラスの場合、Platform.runLater()fire(Event event)メソッドの呼び出しを囲むかEventBusクラス変更:最適化として

    public class EventBus { 
    
        public static final EventBus INSTANCE = new EventBus(); 
    
        private final Set<EventListener> listeners; 
    
        private EventBus() { 
         listeners = new HashSet<>(); 
        } 
    
        public void register(EventListener listener) { 
         listeners.add(listener); 
        } 
    
        public void fire(Event event) { 
         Platform.runLater(() -> { 
          listeners.forEach(listener -> listener.eventFired(event));  
         }); 
        } 
    } 
    
    +0

    をあなたはまた、HTTPS([Platform.isFXApplicationThread()]、火の中にチェックを実行できます。 //docs.oracle.com/javase/8/javafx/api/javafx/application/Platform.html#isFxApplicationThread--)、FXスレッドで実行されていない場合はrunLaterだけです。そうでない場合はすぐに実行します。 – jewelsea

    +0

    ありがとう!最初の提案( 'fire(イベントイベント)'の呼び出しを取り巻く)は完璧に機能しました! – ivko

    関連する問題