2016-11-26 1 views
1

Mein Programm sendet eine Nachricht an den Server, die in einem Fenster angezeigt wird und eine Nachricht von einem Fenster empfängt, das auch im Fenster des Clients hinzugefügt wird.Hinzufügen von Elementen in TextFlow mit externem Thread in JavaFX

Aber mein Programm zeigt nicht die Nachricht vom Server empfangen, obwohl ich hinzugefügt:

textFlow.getChildren().add(text); in akzeptiert Fäden.

Was soll ich tun?

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

Immer noch versuchen, die Benutzeroberfläche von einem Thread zu aktualisieren, die nicht der Anwendungs-Thread ist? – fabian

+0

Wie kann ich dann Nachrichten erhalten und an mein TextField anhängen? Ich bin ziemlich neu in JavaFX, können Sie mir bitte sagen, wo sollte ich Änderungen vornehmen, damit es richtig funktioniert? – IAmBlake

+0

@fabian danke aber kannst du mir bitte vorschlagen, wo ich platform.runlater() anrufen soll? – IAmBlake

Antwort

1

sollten Sie verwenden:

Platform.runLater(()->{ 

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

}); 

Der Scenegraph darf nicht von anderen Threads geändert werden. Nur JavaFX main Thread kann den SceneGraph ändern.

So diese Methode aufrufen Sie senden dieses Runnable Objekt zu einem QUEUE und es wird von den JavaFX Main Thread genannt werden, um die Szenengraphen zu ändern.


Was ist der SceneGraph?

Die GUI in JavaFX ist als Szenengraph aufgebaut. Ein Szenengraph ist eine Sammlung von visuellen Elementen, die als Knoten bezeichnet werden und in einer hierarchischen Weise angeordnet sind. Ein Szenengraph wird mithilfe der öffentlichen JavaFX-API erstellt.


Wie Ereignisse in JavaFX verwaltet werden?

In JavaFX, Ereigniswarteschlangen werden von einem einzigen, auf Betriebssystemebene Thread aufgerufen JavaFX Anwendung Gewinde verwaltet. Alle Benutzereingabeereignisse sind , die auf dem JavaFX-Anwendungsthread ausgelöst werden. JavaFX erfordert, dass ein Live-Szenen-Diagramm nur für den Thread JavaFX Application geändert werden muss.


Wo sollte ich Platform.runLater (() -> {....});

Jeder, wo Sie eine Live Scenegraph von einem externen Thread andere als JavaFX Main Thread modifizieren.

Zusätzliche Links:

How JavaFX application thread works?

Platform.runLater and Task in JavaFX

+0

sollte ich es innerhalb accept thread nennen? – IAmBlake

+0

@IAmBlake Sie können es von jedem externen Thread aufrufen. Der Code wird nach einigen Millisekunden vom 'JavaFX Main Thread' ausgeführt. Schauen Sie sich den Link zum Kommentar von 'Fabian' an. – GOXR3PLUS

+0

i hinzugefügt, dass Teil Thread akzeptieren, aber es funktioniert immer noch nicht – IAmBlake

Verwandte Themen