multithreading - Javafx Stage.show() 稍后打开
问题描述
当我运行此代码时,阶段会在任务完成后显示。为什么会这样?如何使阶段出现在任务之前?
private List<SensorEntity> detectSensors() throws URISyntaxException {
Task<List<SensorEntity>> task = new TryDetectTask(sensorForDiscover, wifiController);
ProgressIndicator indicator = new ProgressIndicator();
indicator.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
indicator.progressProperty().bind(task.progressProperty());
Stage stage = new Stage();
stage.setHeight(100);
stage.setWidth(200);
stage.initModality(WINDOW_MODAL);
stage.setScene(new Scene(indicator));
stage.show();
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<List<SensorEntity>> futureTask = executor.submit(task, null);
try {
return futureTask.get(30, SECONDS);
}
catch (InterruptedException | ExecutionException | TimeoutException e) {
log.error(e);
e.printStackTrace();
}
executor.shutdown();
return null;
}
pane.getScene().setRoot()、alert.show()、Platform.runLater 等的结果相同,但 showAndWait() 工作正常。
解决方案
futureTask.get(30, SECONDS)
阻塞,直到结果可用或 30 秒过去。由于您在 JavaFX 应用程序线程上执行此操作,因此在此期间阻止对 GUI 的任何更新。
showAndWait
“有效”,因为此调用确保 GUI 仍然更新,但此方法仅在阶段关闭时返回,这意味着您稍后只需冻结 GUI。
您最好将 a 传递Consumer<List<SensorEntity>>
给使用任务结果执行代码的方法。
private void detectSensors(Consumer<List<SensorEntity>> consumer) throws URISyntaxException {
final boolean[] boolRef = new boolean[1];
Task<List<SensorEntity>> task = new TryDetectTask(sensorForDiscover, wifiController);
task.setOnSucceeded(evt -> {
if (!boolRef[0]) {
boolRef[0] = true;
// submit result unless timeout happened
consumer.accept(task.getValue());
}
});
ProgressIndicator indicator = new ProgressIndicator();
indicator.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
indicator.progressProperty().bind(task.progressProperty());
Stage stage = new Stage();
stage.setHeight(100);
stage.setWidth(200);
stage.initModality(WINDOW_MODAL);
stage.setScene(new Scene(indicator));
stage.show();
// a thread does not need to be shut down
Thread thread = new Thread(task);
thread.setDaemon(true);
PauseTransition pause = new PauseTransition(Duration.seconds(30));
pause.setOnFinished(evt -> {
if (!boolRef[0]) {
boolRef[0] = true;
// submit null unless task has finished successfully
consumer.accept(null);
}
});
thread.start();
pause.play();
}
推荐阅读
- json - HIGHCHARTS POINTSTART 今天日期
- ruby-on-rails - 库未加载 libssl.1.0.0.dylib
- rest - 如何将 SOAP 请求转换为 REST 请求?
- r - 如何对多列中小写值的数据框进行子集化
- mysql - How to explode mySQL column into REGEXP?
- spring - Spring Data Reactive Mongo 模板:MongoDB 游标
- firebase - Kotlin - 可序列化类中的初始化块只能读取默认属性值
- php - 为什么我的 ajax 函数不是异步的并刷新页面?
- python - 将列值聚合到列表中,忽略 Pandas 数据框中的 None 值
- flutter - 如何在后台运行蓝牙和位置代码?