英文:
Popup intended to display ProgressBar not showing in JavaFX
问题
我想在JavaFX中使用Popup
来显示一个ProgressBar
,以便我可以通过调用Popup
的hide()
方法来使ProgressBar
消失。然而,与其在后台任务完成时消失,ProgressBar
根本不显示。
当我运行上面的代码时,我只看到一个空白的舞台,如下所示:
如果我使用root.getChildren().add(bar)
将ProgressBar
手动添加到Stage
中,进度条将正确显示,并且其progressProperty
正确绑定,因此我知道问题出在Popup
上。然而,使用该方法,进度条在后台任务完成时不会消失。
英文:
I want to display a ProgressBar
using a Popup
in JavaFX so that I will be able to make the ProgressBar
disappear by calling the PopUp
's hide()
method. However, rather than disappearing when the background task is complete, the ProgessBar
doesn't show at all.
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage stage) {
StackPane root = new StackPane();
Popup popup = new Popup();
ProgressBar bar = new ProgressBar();
popup.getContent().add(bar);
Task<Void> task = new Task<>() {
@Override
protected Void call() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
updateProgress(i, 100);
} catch (Exception ignored) {
}
}
return null;
}
};
bar.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(workerStateEvent -> popup.hide());
popup.show(stage);
new Thread(task).start();
stage.setScene(new Scene(root, 100, 100));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
When I run the above code, all I see is a blank stage, shown here:
If I add the ProgressBar
to the Stage
manually using root.getChildren().add(bar)
, the bar displays correctly, with its progressProperty
properly bonded, so I know that the issue is with the Popup
. However, using that method, the bar doesn't disappear when the background task is complete.
答案1
得分: 3
以下是翻译好的部分:
"我无法在任何地方找到这个记录,但我认为Popup
的所有者必须显示出来,Popup.show(owner)
方法才能成功。因此,您代码的以下重新排序(在popup.show(stage)
之前调用stage.show()
)可以工作:
@Override
public void start(Stage stage) {
StackPane root = new StackPane();
Popup popup = new Popup();
ProgressBar bar = new ProgressBar();
popup.getContent().add(bar);
Task<Void> task = new Task<>() {
@Override
protected Void call() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
updateProgress(i, 100);
} catch (Exception ignored) {
}
}
return null;
}
};
bar.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(workerStateEvent -> popup.hide());
stage.setScene(new Scene(root, 100, 100));
stage.show();
popup.show(stage);
new Thread(task).start();
}
请注意,您的另一种方法也可以工作:只需在任务完成时从场景图中移除进度条:
@Override
public void start(Stage stage) {
StackPane root = new StackPane();
// Popup popup = new Popup();
ProgressBar bar = new ProgressBar();
// popup.getContent().add(bar);
root.getChildren().add(bar);
Task<Void> task = new Task<>() {
@Override
protected Void call() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
updateProgress(i, 100);
} catch (Exception ignored) {
}
}
return null;
}
};
bar.progressProperty().bind(task.progressProperty());
// task.setOnSucceeded(workerStateEvent -> popup.hide());
task.setOnSucceeded(event -> root.getChildren().remove(bar));
stage.setScene(new Scene(root, 100, 100));
stage.show();
// popup.show(stage);
new Thread(task).start();
}
英文:
I can't find this documented anywhere, but I think the owner of a Popup
must be showing for the Popup.show(owner)
method to succeed. So the following reordering of your code (calling stage.show()
before popup.show(stage)
) works:
@Override
public void start(Stage stage) {
StackPane root = new StackPane();
Popup popup = new Popup();
ProgressBar bar = new ProgressBar();
popup.getContent().add(bar);
Task<Void> task = new Task<>() {
@Override
protected Void call() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
updateProgress(i, 100);
} catch (Exception ignored) {
}
}
return null;
}
};
bar.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(workerStateEvent -> popup.hide());
stage.setScene(new Scene(root, 100, 100));
stage.show();
popup.show(stage);
new Thread(task).start();
}
Note your other approach works: you just have to remove the progress bar from the scene graph when the task is complete:
@Override
public void start(Stage stage) {
StackPane root = new StackPane();
// Popup popup = new Popup();
ProgressBar bar = new ProgressBar();
// popup.getContent().add(bar);
root.getChildren().add(bar);
Task<Void> task = new Task<>() {
@Override
protected Void call() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
updateProgress(i, 100);
} catch (Exception ignored) {
}
}
return null;
}
};
bar.progressProperty().bind(task.progressProperty());
// task.setOnSucceeded(workerStateEvent -> popup.hide());
task.setOnSucceeded(event -> root.getChildren().remove(bar));
stage.setScene(new Scene(root, 100, 100));
stage.show();
// popup.show(stage);
new Thread(task).start();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论