我尝试了解如何在多线程环境中更新ProgressBar。我在这里做错了但我不知道它是什么。这应该只是每3秒填满一次,但不会:
Task<Void> task = new Task<Void>(){
@Override
public Void call(){
for (int i = 1; i < 10; i++) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
updateProgress(i , 10);
}
return null;
}
};
updProg = new ProgressBar();
updProg.progressProperty().bind(task.progressProperty());
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
我错过了什么?
答案 0 :(得分:9)
你的样本对我来说很好。
样品每3秒钟填充一次,在半分钟内完全填满酒吧。
我只是将它包装在一些脚手架代码中,以使其可执行,并且无需更改即可正常工作(java7u15,win7)。
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ProgressTest extends Application {
public static void main(String[] args) { Application.launch(args); }
@Override public void start(Stage stage) {
Task<Void> task = new Task<Void>() {
@Override public Void call() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.interrupted();
break;
}
System.out.println(i + 1);
updateProgress(i + 1, 10);
}
return null;
}
};
ProgressBar updProg = new ProgressBar();
updProg.progressProperty().bind(task.progressProperty());
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
StackPane layout = new StackPane();
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
layout.getChildren().add(updProg);
stage.setScene(new Scene(layout));
stage.show();
}
}
也许你一直在使用Java 8的一些早期访问版本,它在ProgressBar更新中有一个错误(现已修复)。
RT-29018 ProgressBar and ProgressIndicator disappear when progressProperty is updated
答案 1 :(得分:1)
您使用的是最新的JDK 8 Early-Access吗?如果是这样,请参阅我提交的错误报告:http://javafx-jira.kenai.com/browse/RT-29018
基本上,在早期版本的早期版本中,他们对皮肤和CSS进行了一些更改。这导致了一个隐藏的错误,其中哪个子节点比父节点更脏,但都需要在同一个脉冲中重新绘制,父节点的脏级别最终会覆盖子节点的脏级别。
这会导致进度无法显示,事实上,对于我来说,progressBar
只要从任务中调用updateProgress
就会变得完全不可见。他们有一个补丁,我不知道什么时候会这样。
解决方法,在修补程序上等待时使用jdk7,或者你可以做我所做的并将这个从旧的css应用到你的css样式表中:
/*hack to get progress bar working. From: JDK7u17 jfxrt.jar!/com/sun/javafx/scene/control/skin/caspian/caspian.css */
/*******************************************************************************
* *
* ProgressBar *
* *
******************************************************************************/
.progress-bar {
-fx-skin: "com.sun.javafx.scene.control.skin.ProgressBarSkin";
-fx-background-color:
-fx-box-border,
linear-gradient(to bottom, derive(-fx-color,30%) 5%, derive(-fx-color,-17%));
-fx-background-insets: 0, 1;
-fx-indeterminate-bar-length: 60;
-fx-indeterminate-bar-escape: true;
-fx-indeterminate-bar-flip: true;
-fx-indeterminate-bar-animation-time: 2;
-fx-focus-traversable: true;
}
.progress-bar .bar {
-fx-background-color:
-fx-box-border,
linear-gradient(to bottom, derive(-fx-accent,95%), derive(-fx-accent,10%)),
linear-gradient(to bottom, derive(-fx-accent,38%), -fx-accent);
-fx-background-insets: 0, 1, 2;
-fx-padding: 0.416667em; /* 5 */
}
.progress-bar:indeterminate .bar {
-fx-background-color: linear-gradient(to left, transparent, -fx-accent);
}
.progress-bar .track {
-fx-background-color:
-fx-box-border,
linear-gradient(to bottom, derive(-fx-color,-15%), derive(-fx-color,2.2%) 20%, derive(-fx-color,60%));
-fx-background-insets: 0, 1;
}
.progress-bar:disabled {
-fx-opacity: 1.0
}
答案 2 :(得分:0)
如果在FXML文件中定义了updProg,那么问题可能就是初始化。
尝试删除此行:
updProg = new ProgressBar();
答案 3 :(得分:0)
Timeline updateProgressBar = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
/*Where Seconds and TotalSeconds are counter and total
respectively, also put somewhere Seconds++ or
however you want to update progress. This time line
will reapit each second */
progressBar.setProgress(Seconds / TotalSeconds);
}
}));
updateProgressBar.setCycleCount(Timeline.INDEFINITE);
updateProgressBar.play();