我可以解释一下如何更新GUI线程吗?对我来说这一切都很混乱。 例如,我想在循环中更新ProgressBar。我知道我需要把循环放到一个新的Task中。我将progressBar的progressProperty绑定到了Task的进度。
如果我用
调用任务new Thread(task).start();
结合调用函数中的Task的updateProgress()方法,它工作正常,progressBar更新。
问题一:为什么我通过直接在循环内设置进度来更新ProgressBar失败(progressProperty没有绑定)?如果我想在循环内部设置(非)可见,也会出现相同的情况。
问题2:将progressProperty绑定到Task.progressProperty。为什么我不能通过使用Plateform.runLater(任务)调用任务来更新progressBar?它不会更新GUI线程。
问题3:如何在循环中设置progressBar的可见性?
public class PRogressBar extends Application {
ProgressBar progressBar;
@Override
public void start(Stage stage) {
/**
Task for updating the ProgressBar
*/
Task<Void> task = new Task() {
@Override
protected Object call() throws Exception {
System.out.println("Init Task");
// progressBar.setVisible(false) // Question 3
// progressBar.setProgress(0.75) // question 1
for (int i = 1; i < 5; i++) {
final int update = i;
try {
Thread.sleep(500);
System.out.println("Run later : " + update/5.0);
updateProgress(i, 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
};
/*
Initializing the GUI
*/
progressBar = new ProgressBar();
Button button = new Button("blou");
button.setOnAction((event) -> {
// Platform.runLater(task); // Question 2
Thread th = new Thread(task);
// th.setDaemon(true);
th.start();
System.out.println("Thread started");
});
StackPane layout = new StackPane();
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
HBox hbox = new HBox(progressBar, button);
layout.getChildren().add(hbox);
progressBar.setProgress(0.1);
// setVisible2(false);
// progressBar.progressProperty().bind(task.progressProperty());
stage.setScene(new Scene(layout));
stage.show();
}
答案 0 :(得分:2)
问题一:为什么我通过直接在循环内设置进度来更新ProgressBar失败(progressProperty没有绑定)?如果我想在循环内部设置(非)可见,也会出现相同的情况。
包含影响当前显示的舞台的UI的所有更改必须在JavaFX应用程序线程中执行。您的任务在您自己的线程中执行,因此请确保在JavaFX应用程序线程中调用 setProgress 和 setVisible 。你必须通过Platform.runLater(() -> { //change UI});
updateProgress 和 updateMessage 线程安全。也许这些方法影响UI,例如。 G。如果您已将progressProperty绑定到ProgressBar。您可以以安全的方式从工作线程中调用它。但是 updateProgress 是例外而不是规则。
问题2:将progressProperty绑定到Task.progressProperty。为什么我不能通过使用Plateform.runLater(任务)调用任务来更新progressBar?它不会更新GUI线程。
你的意思是Platform.runLater(() -> myTask.call());
?这应该有效,因为调用在JavaFX应用程序线程中执行,因此您可以对UI进行更改。但这不是你应该使用任务的方式:)
问题3:如何在循环中设置progressBar的可见性?
您不在JavaFX应用程序线程之外,因此您必须使用Platform.runLater(...)
。
顺便说一句,Brian Goetz在他的书中描述了 Java Concurrency in Practice 第9.1章为什么GUI是单线程的?。