我正在使用JavaFx API的Task class来执行网络操作。该类提供了一个似乎完全适应这种情况的进度系统,例如,允许报告上传到调用者线程的文件数量。为此,每次成功上传文件时都会调用updateMessage(x + "files uploaded")。
问题是我收到的唯一信息是最后一条,当每个文件都被上传时。我想Javadoc以某种方式解释了这种现象:
对updateMessage的调用将在FX应用程序线程上合并并稍后运行,因此即使从FX Application线程调用updateMessage也不一定会立即更新此属性,并且可以合并中间消息值以节省事件通知。
如何正确报告每条或至少部分消息?我试图在它周围添加一些Thread.sleep(20),但它不起作用。有什么想法吗?
答案 0 :(得分:3)
很可能你在事件线程上运行Task,所以它会阻止更新。任务实现了Runnable,这有点误导,但通过查看javadoc,你可以发现正确运行Task的方法是将它分配到新线程:new Thread(task).start();
见下一个例子:
public class TaskTask extends Application {
public static void main(String[] args) { launch(args); }
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle(VersionInfo.getRuntimeVersion());
Button btn = new Button();
final Task<Integer> task = new Task<Integer>() {
@Override
protected Integer call() throws Exception {
int iterations;
for (iterations = 0; iterations < 100; iterations++) {
if (isCancelled()) {
break;
}
Thread.sleep(100); // imitate activity
updateMessage("Iteration " + iterations);
}
return iterations;
}
};
// here we monitor task updates
btn.textProperty().bind(task.messageProperty());
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
//here it goes
new Thread(task).start();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
答案 1 :(得分:1)
好吧,我的错。我错误地收听了消息更新:我在Task上使用了EventHandler,而不是在messageProperty上使用了ChangeListener。 javadoc只指示如何发送更新,而不是接收更新,所以我尝试了,但谢尔盖的答案是正确的方法。