Stage.close()无法使用JavaFX

时间:2018-07-13 18:55:24

标签: java javafx

我有一个主窗口,当我按一个按钮时,将打开另一个窗口。 一定时间后,该窗口应关闭。因为它扩展了stage,所以我使用super.close,但是它不起作用。我能做什么?是因为我在服务任务中关闭了它?

public Game(int width, int height, int time) {
    this.width = width - 15;
    this.height = height - 15;
    this.time = time;

    this.layout = generateLayout();
    this.scene = new Scene(this.layout, this.width, this.height);

    super.initModality(Modality.APPLICATION_MODAL);
    super.setScene(scene);
    super.setResizable(false);
    super.setTitle(TITLE);

    this.cicle.reset();
    this.cicle.start();

    super.showAndWait();
}

cicle内,我称close()

有点困惑,但这是cicle服务任务:

Service<Void> cicle = new Service<Void>() {
    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {
            volatile boolean waiting = false;

            @Override
            protected Void call() throws Exception {
                Timer.start();
                while (Timer.update() / 1000 < time) {
                    System.out.println(Timer.update())
                }
                close();
                return null;
            }
        };
    }
};

1 个答案:

答案 0 :(得分:1)

问题是您正试图从JavaFX Application Thread以外的其他线程 关闭Stage。查看Stage的文档,您将看到:

  

必须在JavaFX上构造和修改阶段对象   应用程序线程。

     

JavaFX应用程序线程是在启动过程中创建的   JavaFX运行时进程。请参阅Application类和   Platform.startup(Runnable)方法以获取更多信息。

然而Service在启动时将在 background 线程上执行其Task。具体地,call()的{​​{1}}方法在所述后台线程上执行。我刚刚测试过尝试在后台线程上关闭Task来查看发生了什么(是否会引发异常)。结果是Stage

您没有看到它的原因是您没有观察到java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3的失败。您可以查看the answer to this question来查看监视失败的方法。答案专门针对Service,但Task中也存在相同的行为。

要使代码正常工作,需要做的是确保在JavaFX Application Thread上调用Service。最简单的方法是将close()封装在Platform.runLater(Runnable)调用中。

close()

您还可以覆盖Service.succeeded(),它将始终在JavaFX Application Thread上调用(但仅在Service<Void> cicle = new Service<Void>() { @Override protected Task<Void> createTask() { return new Task<Void>() { volatile boolean waiting = false; @Override protected Void call() throws Exception { Timer.start(); while (Timer.update() / 1000 < time) { System.out.println(Timer.update()) } Platform.runLater(() -> close()); // wrapped in Platform#runLater return null; } }; } }; 成功的情况下)。在这种情况下,您将从Service方法中删除对close()的调用。

call()

还有其他方法:收听Service<Void> cicle = new Service<Void>() { @Override protected Task<Void> createTask() { return new Task<Void>() { volatile boolean waiting = false; @Override protected Void call() throws Exception { Timer.start(); while (Timer.update() / 1000 < time) { System.out.println(Timer.update()) } return null; } }; } @Override protected void succeeded() { close(); } }; 属性,使用state等...