簡體   English   中英

Stage.close()無法使用JavaFX

[英]Stage.close() doesn't work 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;
            }
        };
    }
};

問題是您試圖從JavaFX Application Thread之外的其他線程關閉Stage 查看Stage的文檔,您將看到:

舞台對象必須在JavaFX Application Thread上構造和修改。

JavaFX應用程序線程是在JavaFX運行時啟動過程中創建的。 有關更多信息,請參見Application類和Platform.startup(Runnable)方法。

然而, Service在啟動時將在后台線程上執行其Task 具體地, Taskcall()方法在所述后台線程上執行。 我剛剛測試過嘗試在后台線程上關閉Stage ,以查看會發生什么(是否會引發異常)。 結果是一個java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3因此,在java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3 java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3

您沒有看到此消息的原因是您沒有觀察到Service的失敗。 您可以查看此問題的答案,以了解觀察失敗的方法。 答案專門討論Task但是Service存在相同的行為。

使代碼工作所需要做的是確保在JavaFX Application Thread上調用close() 最簡單的方法是將close()包裝在Platform.runLater(Runnable)調用中。

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.succeeded() ,它將始終在JavaFX Application Thread上被調用(但僅當Service成功時才調用)。 在這種情況下,您將從call()方法中刪除對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屬性,使用setOnSucceeded(EventHandler)等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM