Javafx Stage.show()稍后打开

时间:2018-07-24 11:53:05

标签: multithreading javafx

运行此代码时,任务完成后会显示阶段。为什么会发生? 如何使阶段出现在任务之前?

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()可以正常工作。

1 个答案:

答案 0 :(得分:1)

futureTask.get(30, SECONDS)将一直阻塞,直到结果可用或经过30秒为止。由于您是在JavaFX应用程序线程上执行此操作,因此在此期间,GUI的所有更新都被阻止。

showAndWait“有效”,因为此调用可确保GUI仍在更新,但是此方法仅在阶段关闭时返回,这意味着您稍后只需冻结GUI。

最好将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();
}