我在我的客户端应用程序中添加了一个gui,
并尝试将套接字消息转发给它。
到目前为止,我嘲笑客户是单身人士,
所以我可以从Application
线程访问它,
但现在我希望多个客户端访问他们的gui。
我知道fxml
绑定了属性监听器但是
我希望尽可能简单。
直接使用线程本身。
我如何让Platform.runLater()
引用
如果Application.launch()
构建自己的场景实例?
我已经阅读了相当广泛但解决方案无处不在
结果是利用fxml
界面跳过我不喜欢的工作。
控制类(简化,第9行问题):
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();}
}
});
}
}
}
用户界面(简化):
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);
}
}
答案 0 :(得分:2)
您应该只拥有Application
子类的一个实例,该实例是通过Application.launch()
启动应用程序时创建的实例。 JavaFX应用程序中的main()
方法实际上只应调用Application.launch()
而不执行任何其他操作;您应该将作为启动过程一部分而调用的start()
(或init()
)方法视为应用程序的入口点。
因此,您应该从Client
方法创建start()
实例,并将其设置为在后台线程中执行的操作。
您可以通过重构代码来实现所有这些目标:
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以任何方式响应,直到读取行)。通过将readLine()
移出Platform.runLater()
块来修复后一个问题。