2016-11-26 33 views
1

我的程序将消息发送到其在一个窗口中显示,并从它也是在客户端的窗口增加了一个窗口收到消息的服务器添加使用外部螺纹上的TextFlow元件。JavaFX中

但我的程序不表明虽然我加入从服务器接收到的消息:

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

仍试图更新从一个线程不是应用程序线程的用户界面? – 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。

所以调用这个方法,你会发送这个Runnable对象到QUEUE,它将被调用从​​来修改SceneGraph。


什么是SceneGraph?

JavaFX中的GUI被构造为场景图。的场景图是 集合的视觉元素,称为节点,布置成层次 时尚。场景图是使用公共JavaFX API构建的。


如何事件JavaFX中进行管理?

在JavaFX中,事件队列是由一个单一的,操作系统级 线程调用的JavaFX应用程序线程管理。所有用户输入事件都是在JavaFX应用程序线程上分派的 。 JavaFX的要求一个 现场场景图只能在JavaFX应用程序 线程修改。


我在哪里应该使用Platform.runLater(() - > {....});

每一个地方你是从外部 Thread以外​​修改现场场景图

额外的链接:

How JavaFX application thread works?

Platform.runLater and Task in JavaFX

+0

我应该在接受线程中调用它吗? – IAmBlake

+0

@IAmBlake你可以从任何外部线程调用它。代码将在'JavaFX主线程'几毫秒后执行。看看“Fabian”评论的链接。 – GOXR3PLUS

+0

我在接受线程中添加了该部分,但它仍然不起作用 – IAmBlake