gpt4 book ai didi

java - 从不同线程修改JavaFX应用程序场景?

转载 作者:行者123 更新时间:2023-12-02 02:30:21 28 4
gpt4 key购买 nike

我已经向我的客户端应用程序添加了一个 GUI,并尝试将套接字消息转发给它。到现在为止我还 mock 客户是单例汉,所以我可以从 Application 线程访问它,但现在我希望多个客户端访问他们的图形用户界面。我知道 fxml 有绑定(bind)属性监听器,但是我希望它尽可能简单。直接使用线程本身。我如何让 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);
}
}

最佳答案

您应该只拥有一个 Application 子类实例,该实例是通过 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 以任何方式响应,直到读取一行)。后一个问题可通过将 readLine() 移出 Platform.runLater() block 来解决。

关于java - 从不同线程修改JavaFX应用程序场景?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47221250/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com