2017-11-10 17 views
0

クライアントアプリケーションにguiを追加しました。 とソケットメッセージを転送しようとしました。 私はクライアントを今までシングルトンに嘲笑して なので、Applicationスレッド からアクセスできましたが、今は複数のクライアントからGUIにアクセスしたいと思っています。 fxmlにはバインドされたプロパティリスナーがありますが、 できるだけ簡単にしたいと思います。 スレッド自体を直接操作する。 どうすれば Application.launch()が独自に構築されている場合、 シーンインスタンスを参照できますか? 私は非常に広範囲に読んだことがありますが、どこでもソリューションを提供しています fxmlインターフェイスを利用して、私が気に入らない作品をスキップしています。 Controlクラス(簡略化され、9行上の問題):JavaFXアプリケーションのシーンを別のスレッドから変更しますか?

public class Client { 
    private Socket socket = new Socket("127.0.0.1",4444); 
    private BufferedReader incoming = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    private Browser browser = new Browser(); 
    public static void main(String[] arguments) throws IOException { 
     Application.launch(browser.class); 
     while(socket.isConnected()) { 
      Platform.runLater(new Runnable(){ 
       @Override public void run(){ 
        try{browser.bubble(incoming.readLine());} 
        catch(IOException fail){fail.printStackTrace();} 
       } 
      }); 
     } 
    } 
} 

ユーザーインターフェイス(簡体字):あなたが唯一のこれまで作成したインスタンスは、あなたのApplicationサブクラスのインスタンスを1つ持っている必要があり

public class Browser extends Application { 
    private Stage stage; 
    private Scene scene; 
    private BorderPane layout = new BorderPane(); 
    private VBox history = new VBox(); 
    @Override public void start(Stage stage) throws Exception { 
     layout.setCenter(history); 
     scene = new Scene(layout); 
     stage = stage; 
     stage.setScene(scene); 
     stage.show(); 
    } 
    public void bubble(String message){ 
     VBox record = new VBox(); 
     Label label = new Label(message); 
     record.getChildren().add(label); 
     history.getChildren().add(record); 
    } 
} 
+1

大部分の場合、mainメソッド以外の場所から 'Application.launch()'を呼び出すべきではありません。メインメソッドでは何もしないでください。これを逆にしてください。私。あなたの 'start()'メソッドから 'Client'インスタンスを作成し、そこから(あなたがバックグラウンドスレッドで)投稿したコードを含むメソッドを呼び出してください。あなたはまだスレッドの問題があります - あなたは 'readLine()'呼び出しでfxアプリケーションスレッドをブロックしています。 –

+0

申し訳ありませんが、訂正したpsvmメソッドを追加していませんでした。私はあなたが描く原則が好きで、メインメソッドで何も他のものをアプリケーションからインスタンス化しています...そのインスタンスを3番目のスレッドにディスパッチすると、ブロッキングの問題も解決できませんでした。 – bpstrngr

答えて

2

アプリケーションはApplication.launch()で起動します。 JavaFXアプリケーションのmain()メソッドは実際にはApplication.launch()を呼び出して何もしません。起動プロセスの一部として呼び出されるstart()(またはinit())メソッドをアプリケーションのエントリポイントとみなしてください。

したがって、start()メソッドからClientインスタンスを作成し、それをバックグラウンドスレッドで実行するように設定する必要があります。

あなたは次のようにコードをリファクタリングして、すべてこれを達成することができます

public class Browser extends Application { 
    private Stage stage; 
    private Scene scene; 
    private BorderPane layout = new BorderPane(); 
    private VBox history = new VBox(); 
    @Override public void start(Stage stage) throws Exception { 
     layout.setCenter(history); 
     scene = new Scene(layout); 
     stage = stage; 
     stage.setScene(scene); 
     stage.show(); 

     Client client = new Client(this); 
     Thread thread = new Thread(client::processIncomingData); 
     thread.setDaemon(true); 
     thread.start(); 
    } 
    public void bubble(String message){ 
     VBox record = new VBox(); 
     Label label = new Label(message); 
     record.getChildren().add(label); 
     history.getChildren().add(record); 
    } 
    public static void main(String[] args) { 
     Application.launch(args); 
    } 
} 

public class Client { 
    private Socket socket = new Socket("127.0.0.1",4444); 
    private BufferedReader incoming = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    private Browser browser ; 

    public Client(Browser browser) { 
     this.browser = browser ; 
    } 

    public void processIncomingData() { 
     while(socket.isConnected()) { 
      try { 
       String data = incoming.readLine(); 
       Platform.runLater(() -> browser.bubble(data)); 
      } catch (IOException exc) { 
       // TODO: handle properly 
       exc.printStackTrace(); 
      } 
     } 
    } 
} 

注意すべき他の物事のカップル:アプリケーションが終了するまでApplication.launch()ブロックを。元のコードでは、whileループはアプリケーションが終了するまで開始されませんでした。また、readLine()メソッドはブロックされているため、FXアプリケーションスレッドでは実行したくない(行が読み込まれるまでUIが応答しないようにする)。後者の問題はPlatform.runLater()ブロックからreadLine()を移動することで修正されています。

+0

申し訳ありませんので、私はロジックを反転し、アプリケーションスレッドからインスタンス化しました。十分にいいですね。ループの前に 'Application.launch()'を挿入するのは私の短縮の間違いでしたが、言及するのは嬉しいです。ありがとう、ジェームス。 – bpstrngr

関連する問題