簡體   English   中英

JavaFX:舞台關閉處理程序

[英]JavaFX: Stage close handler

我想在關閉 JavaFX 應用程序之前保存一個文件。

這就是我在Main::start設置處理程序的方式:

primaryStage.setOnCloseRequest(event -> {
    System.out.println("Stage is closing");
    // Save file
});

當按下按鈕時控制器調用Stage::close

@FXML
public void exitApplication(ActionEvent event) {
    ((Stage)rootPane.getScene().getWindow()).close();
}

如果我單擊窗口邊框上的紅色 X 關閉窗口(正常方式),則會收到輸出消息“ Stage is closing ”,這是所需的行為。

但是,當調用Controller::exitApplication ,應用程序關閉而不調用處理程序(沒有輸出)。

如何讓控制器使用我添加到primaryStage的處理程序?

如果您查看Application類的生命周期

每當啟動應用程序時,JavaFX 運行時都會按順序執行以下操作:

  1. 構造指定的 Application 類的實例
  2. 調用init()方法
  3. 調用start(javafx.stage.Stage)方法
  4. 等待應用程序完成,這在以下任一情況發生時發生:
    • 應用程序調用Platform.exit()
    • 最后一個窗口已關閉,並且Platform上的implicitExit屬性為true
  5. 調用stop()方法

這意味着您可以在控制器上調用Platform.exit()

@FXML
public void exitApplication(ActionEvent event) {
   Platform.exit();
}

只要你覆蓋主類上的stop()方法來保存文件。

@Override
public void stop(){
    System.out.println("Stage is closing");
    // Save file
}

如您所見,通過使用stop()您不再需要監聽關閉請求來保存文件(盡管如果您想阻止窗口關閉,您可以這樣做)。

假設您想詢問用戶是否要退出應用程序而不保存工作。 如果用戶選擇否,則無法避免應用程序在 stop 方法中關閉。 在這種情況下,您應該為 WINDOW_CLOSE_REQUEST 事件向窗口添加一個 EventFilter

在您的 start 方法中添加此代碼以檢測事件:

(請注意,調用 Platform.exit(); 不會觸發 WindowEvent.WINDOW_CLOSE_REQUEST 事件,請參閱下文以了解如何從自定義按鈕手動觸發事件)

// *** Only for Java >= 8 ****
// ==== This code detects when an user want to close the application either with
// ==== the default OS close button or with a custom close button ====

primaryStage.getScene().getWindow().addEventFilter(WindowEvent.WINDOW_CLOSE_REQUEST, this::closeWindowEvent);

然后添加您的自定義邏輯。 在我的示例中,我使用警報彈出窗口詢問用戶他/她是否要關閉應用程序而不保存。

private void closeWindowEvent(WindowEvent event) {
        System.out.println("Window close request ...");

        if(storageModel.dataSetChanged()) {  // if the dataset has changed, alert the user with a popup
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.getButtonTypes().remove(ButtonType.OK);
            alert.getButtonTypes().add(ButtonType.CANCEL);
            alert.getButtonTypes().add(ButtonType.YES);
            alert.setTitle("Quit application");
            alert.setContentText(String.format("Close without saving?"));
            alert.initOwner(primaryStage.getOwner());
            Optional<ButtonType> res = alert.showAndWait();

            if(res.isPresent()) {
                if(res.get().equals(ButtonType.CANCEL))
                    event.consume();
            }
        }
    }

event.consume()方法防止應用程序關閉 顯然,您應該至少添加一個允許用戶關閉應用程序的按鈕,以避免用戶強制關閉應用程序,這在某些情況下可能會損壞數據。

最后,如果您必須從自定義關閉按鈕觸發事件,您可以使用:

Window window = Main.getPrimaryStage()  // Get the primary stage from your Application class
                .getScene()
                .getWindow();

window.fireEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSE_REQUEST));

啊,這是 JavaFX 中的一個已知錯誤,如果在關閉時出現模式對話框,舞台將不會關閉。 我會將您鏈接到我今天剛剛看到的錯誤報告。 認為它已在最新版本中修復。

干得好:

https://bugs.openjdk.java.net/browse/JDK-8093147?jql=text%20~%20%22javafx%20re-entrant%22

它說在 8.4 中解決了。 我想這就是你所描述的。

public Stage getParentStage() {
    return (Stage) getFxmlNode().getScene().getWindow();
}

btnCancel.setOnAction(e -> {
    getParentStage().close();
});

暫無
暫無

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

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