2016-11-26 6 views
1

私のプログラムは、ウィンドウに表示されるメッセージをサーバーに送信し、クライアントのウィンドウにも追加されたウィンドウからメッセージを受け取ります。JavaFXの外部スレッドを使用してTextFlowに要素を追加する

しかし、私が追加されても、サーバから受信したメッセージが表示されない私のプログラムは:

textFlow.getChildren().add(text);スレッドを受け入れます。

どうすればよいですか?

public class NewClient extends Application { 

Thread send; 
Thread accept; 

DatagramPacket pack; 
DatagramSocket sock; 
private List<String> str; 
String name , sname; 
int listeningPort; 
InetAddress server_ip; 

String sender; 
ScrollPane sp = new ScrollPane(); 
TextFlow textFlow = new TextFlow(); 
TextField userTextField = new TextField(); 
TextField fTextField = new TextField(); 

private String message; 
private String recip = null; 
Button button = new Button("Send"); 

volatile boolean st = false; 
Stage theStage; 

public Scene Chat_Box() { 

    TextFlow textFlow = new TextFlow(); 
    textFlow.setPadding(new Insets(10)); 
    textFlow.setLineSpacing(10); 
    TextField textField = new TextField(); 
    textField.setPrefSize(50, 30); 
    Button button = new Button("Send"); 
    button.setPrefSize(80, 30); 
    VBox container = new VBox(); 
    VBox box = new VBox(); 
    box.getChildren().addAll(sp, textFlow); 
    container.setPadding(new Insets(10)); 
    container.getChildren().addAll(box, new HBox(textField, button)); 
    VBox.setVgrow(sp, Priority.ALWAYS); 
    VBox.setVgrow(textFlow, Priority.ALWAYS); 

    textField.prefWidthProperty().bind(container.widthProperty().subtract(button.prefWidthProperty())); 

    textField.setOnKeyPressed(e -> { 
     if (e.getCode() == KeyCode.ENTER) { 
      button.fire(); 
     } 
    }); 
    button.setOnAction(e -> { 
     st = true; 
     Text text; 
     if (textFlow.getChildren().size() == 0) { 
      text = new Text(textField.getText()); 
      message = textField.getText(); 
      System.out.println(message); 
     } else { 
      message = textField.getText(); 
      text = new Text("\n" + textField.getText()); 
     } 
     if (textField.getText().contains(":)")) { 
      ImageView imageView = new ImageView(
        "http://files.softicons.com/download/web-icons/network-and-security-icons-by-artistsvalley/png/32x32/Regular/Friend%20Smiley.png"); 
      // Remove :) from text 
      text.setText(text.getText().replace(":)", " ")); 
      textFlow.getChildren().addAll(text, imageView); 
     } else { 
      textFlow.getChildren().add(text); 
     } 
     textField.clear(); 
     textField.requestFocus(); 
    }); 
    VBox vb = new VBox(); 
    vb.getChildren().addAll(textFlow); 
    sp.setVmax(440); 
    sp.setPrefSize(400, 300); 
    sp.setContent(vb); 
    sp.vvalueProperty().bind((ObservableValue<? extends Number>) vb.heightProperty()); 
    Scene scene2 = new Scene(container, 400, 300); 
    return scene2; 
} 

public void start(Stage stage) throws IOException { 
    this.str = getParameters().getRaw(); 
    name = str.get(0); 
    listeningPort = Integer.parseInt(str.get(1)); 
    server_ip = InetAddress.getByName(str.get(2)); 
    theStage = stage; 
    Scene scene = Chat_Box(); 
    stage.setScene(scene); 
    stage.show(); 
    send = new Thread() { 

     public void run() { 
      DatagramSocket sock = null; 
      try { 
       sock = new DatagramSocket(); 
      } catch (SocketException ex) { 
       Logger.getLogger(NewClient.class.getName()).log(Level.SEVERE, null, ex); 
      } 
      while (true) { 
       InetAddress host = server_ip; 
       try { 
        if (st && (message != null)) { 
         String in = message; 
         byte[] data = new byte[1024]; 
         data = in.getBytes(); 
         DatagramPacket sendPack = new DatagramPacket(data, data.length); 
         sendPack.setPort(5050); 
         sendPack.setAddress(host); 
         sock.send(sendPack); 
         st = false; 
        } 
       } catch (Exception e) { 
        System.out.println(e); 
       } 
      } 
     } 

    }; 
    send.start(); 
    accept = new Thread() { 

     public void run() { 
      try { 
       sock = new DatagramSocket(listeningPort); 
      } catch (SocketException e) { 
       e.printStackTrace(); 
      } 
      while (true) { 
       byte[] data = new byte[1024]; 
       pack = new DatagramPacket(data, data.length); 
       try { 
        sock.receive(pack); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
       String incoming = null; 
       try { 
        incoming = new String(data, "UTF-8"); 
       } catch (UnsupportedEncodingException e) { 
        e.printStackTrace(); 
       } 
       Text text = new Text(incoming); 
       textFlow.getChildren().add(text); 
      } 
     } 
    }; 
    accept.start(); 
} 

public static void main(String[] args) throws IOException { 
    launch(args); 
} 

} 
+1

はまだアプリケーションスレッドではないスレッドからUIを更新しようと? – fabian

+0

メッセージを受信して​​textFieldに追加するにはどうすればよいですか?私はjavaFXで新しくなっています。正しく動作させるためにどこに変更を加えるべきですか教えてください。 – IAmBlake

+0

@fabianありがとう、私はどこで私はplatform.runlater()を呼び出す必要があります私にお勧めしますか? – IAmBlake

答えて

1

あなたは使用する必要があります。

Platform.runLater(()->{ 

Text text = new Text(incoming); 
textFlow.getChildren().add(text); 

}); 

シーングラフは、他のThreadsから変更することが許可されていません。 JavaFX main ThreadのみがSceneGraphを変更できます。

ですから、QUEUEにこのRunnableオブジェクトを送るこのメソッドを呼び出すと、シーングラフを変更するために​​から呼び出されます。


シーングラフとは何ですか?

JavaFXのGUIは、シーングラフとして作成されます。シーングラフは、 様式で配列されたノードと呼ばれる視覚的要素の の集合である。シーングラフは、public JavaFX APIを使用して構築されます。イベントはJavaFXの中で管理されている方法


JavaFXでは、イベントキューは、JavaFXアプリケーションスレッドと呼ばれる単一のオペレーティングシステムレベルの スレッドによって管理されます。すべてのユーザー入力イベントは、JavaFXアプリケーションスレッドにディスパッチされた です。 JavaFXでは、 ライブシーングラフをJavaFXアプリケーション スレッドでのみ変更する必要があります。 iはPlatform.runLaterを(() - > {...})を使用する必要があり


あなたは​​以外の外部 Threadからライブシーングラフを変更しているすべての。

エクストラリンク:

How JavaFX application thread works?

Platform.runLater and Task in JavaFX

+0

私はそれをaccept thread内で呼び出すべきですか? – IAmBlake

+0

@IAmBlake外部スレッドから呼び出すことができます。コードは 'JavaFX Main Thread'から数ミリ秒後に実行されます。 'Fabian'のコメントのリンクを見てください。 – GOXR3PLUS

+0

私はその部分を承認スレッドに追加しましたが、それでも動作しません – IAmBlake

関連する問題