我正在使用一种应用程序功能来显示TextArea中的进度状态。我正在使用观察者模式来实现这一点。但是,当我尝试将状态信息附加到TextArea时,窗口冻结。如何解决这个问题?

冻结窗口如下:

java - 尝试显示后台进程状态时,JavaFX应用程序窗口卡住-LMLPHP

doSomething()完成后。冻结窗口恢复正常。像这样:

java - 尝试显示后台进程状态时,JavaFX应用程序窗口卡住-LMLPHP

这是我的代码

start(Stage stage)


FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("view/progressStatus.fxml"));
Parent root = loader.load();
statusStage = new Stage();
statusScene = new Scene(root);
statusStage.setScene(statusScene);
progressStatusController = loader.getController();
statusStage.show();
MyFiles myFiles = new MyFiles();
myFiles.addObserver(progressStatusController);
newMyFiles.doSomething();




public class ProgressStatusController implements Initializable, Observer {
    @FXML private ProgressBar progressBar;
    @FXML private TextArea textArea;
    private String[] message;
    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }
    @Override
    public void update(Observable o, Object arg) {
        System.out.println(arg);
        textArea.textProperty().set(textArea.getText().concat("\n").concat((String)arg));
        textArea.positionCaret(textArea.getText().length());
    }
}

最佳答案

doSomething是一项长期运行的任务,因此不应在JavaFX应用程序线程上运行。但是,start方法在此线程上运行。

您需要在其他线程上运行doSomething以避免阻塞应用程序线程。对UI的更新应在应用程序线程上完成;因此,您应该使用Platform.runLater执行更新:

...
MyFiles myFiles = new MyFiles();
myFiles.addObserver(progressStatusController);
new Thread(newMyFiles::doSomething).start();




@Override
public void update(Observable o, Object arg) {
    System.out.println(arg);
    Platform.runLater(() -> {
        textArea.setText(textArea.getText() + "\n" + arg);
        textArea.positionCaret(textArea.getText().length());
    });
}

09-10 06:42
查看更多