这是我的应用程序的主窗口:
我希望能够更新窗口,所以我写了一个方法reset
按 F5 触发:
public void reset() {
final ProgressIndicator pi = new ProgressIndicator(-1.0f);
final HBox hb = new HBox(pi);
final VBox vb = new VBox(hb);
hb.setAlignment(Pos.CENTER);
vb.setAlignment(Pos.CENTER);
scene.setRoot(vb);
//this.show();
}
如果我运行它,它看起来像这样:
但是,如果我取消注释 //this.show();
行这将被执行:
public void show() {
final VBox box = API_CALL_AND_BUILDING_BOX_MAGIC_WHICH_I_STRIPPED;
gp.getChildren().clear();
gp.getChildren().add(box);
scene.setRoot(gp);
stage.sizeToScene();
}
我将永远无法看到我的 ProgressIndicator,因为应用程序将挂起,直到 API 调用完成并加载新内容。
我尝试了一些 Threads 和 Platform.runLater() 但无法让它工作。我的目标是显示 ProgressIndicator,直到 API 调用完成、盒子构建完毕并且场景被给出 gp
作为新的根。
我希望我的目标和问题是可以理解的:)
最佳答案
您需要创建另一个专用于从远程源获取数据的 JVM 线程。应用程序的主线程绝不能因网络操作而阻塞:在键盘事件处理程序中,您只需使用进度指示器重新绘制主窗口,然后等待另一个事件,该事件可以是:
- 后台操作完成(成功、不成功)
- 用户中断(鼠标/键盘)
- 超时到期
伪代码 ListenableFuture通过 Guava
// Initialize in ctor use MoreExecutors
private final ListeningExecutorService service;
// Keep to call .cancel()
private ListenableFuture<APIData> currentRequest;
// Run in the GUI thread
public void onRefreshEvent() {
showProgressIndicator();
currentRequest = service.submit(/* Some Callable<APIData> */);
Futures.addCallback(currentRequest , this, this);
}
// From FutureCallback<T>
public void onFailure(Throwable t) {} // TODO
public void onSuccess(APIData d) {} // TODO
// From Executor
public void execute(Runnable cmd) {
Platform.runLater(cmd);
}
不要忘记考虑套接字连接和读取超时,以及池化 HTTP 连接!还要考虑后台任务是否应该检查中断标志
关于javafx 在加载时显示进度指示器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34773577/