final ProgressBar bar = new ProgressBar();
new Thread(new Runnable() {
@Override public void run() {
for (int i = 1; i <= 1000000; i++) {
final int counter = i;
Platform.runLater(new Runnable() {
@Override public void run() {
bar.setProgress(counter / 1000000.0);
}
});
}
}).start();
Task task = new Task<Void>() {
@Override public Void call() {
static final int max = 1000000;
for (int i = 1; i <= max; i++) {
updateProgress(i, max);
}
return null;
}
};
ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();
4 回答
使用
Platform.runLater(...)
进行快速简单的操作,使用Task
进行复杂和大型操作 .Use case for Platform.runLater(...)
Use case for Task: Task Example in Ensemble App
示例:为什么我们不能使用
Platform.runLater(...)
进行长时间计算(取自下面的参考) .问题:后台线程只需0到100万,并在UI中更新进度条 .
Code using Platform.runLater(...):
Code using Task :
Reference : Worker Threading in JavaFX 2.0
Platform.runLater
:如果需要从非GUI线程更新GUI组件,可以使用它来将更新放入队列中,并尽快由GUI线程处理 .Task
实现Worker
接口,当您需要在GUI线程外运行长任务(以避免冻结您的应用程序)时使用该接口,但仍需要在某个阶段与GUI交互 .如果你熟悉Swing,前者相当于
SwingUtilities.invokeLater
,后者相当于SwingWorker
的概念 .javadoc of Task给出了很多例子,应该说明如何使用它们 . 您也可以参考the tutorial on concurrency .
它现在可以更改为lambda版本
使用explicite Platform.runLater()的一个原因可能是您将ui中的属性绑定到service(result)属性 . 因此,如果更新绑定服务属性,则必须通过runLater()执行此操作:
在UI线程中也称为JavaFX Application线程:
在服务实现(后台工作者):