JavaFX:阶段关闭处理程序

JavaFX:阶段关闭处理程序,java,javafx,handler,javafx-8,Java,Javafx,Handler,Javafx 8,我想在关闭JavaFX应用程序之前保存一个文件 这就是我在Main::start中设置处理程序的方式: primaryStage.setOnCloseRequest(event -> { System.out.println("Stage is closing"); // Save file }); 当按下按钮时,控制器调用Stage::close: @FXML public void exitApplication(ActionEvent event) { ((

我想在关闭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
的处理程序?

每当 申请已推出:

  • 构造指定应用程序类的实例
  • 调用
    init()
    方法
  • 调用
    start(javafx.stage.stage)
    方法
  • 等待应用程序完成,发生以下任一情况时会发生这种情况:
    • 应用程序调用
      Platform.exit()
    • 最后一个窗口已关闭,
      Platform
      上的
      implicitExit
      属性为
      true
  • 调用
    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()
    您不再需要监听关闭请求来保存文件(尽管如果您想阻止窗口关闭,您可以这样做)。

    假设您想询问用户是否希望在不保存工作的情况下退出应用程序。如果用户选择“否”,则无法避免应用程序在停止方法中关闭。在这种情况下,您应该为窗口关闭请求事件向窗口添加一个事件过滤器

    在start方法中,添加以下代码以检测事件:

    (请注意,调用Platform.exit();不会触发WindowEvent.WINDOW\u CLOSE\u请求事件,,请参见下文了解如何从自定义按钮手动触发事件)

    然后添加自定义逻辑。在我的示例中,我使用一个警报弹出窗口询问用户是否希望在不保存的情况下关闭应用程序

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

    啊,这是JavaFX中的一个已知错误,如果在关闭时出现模式对话框,阶段将不会关闭。我将把你链接到我今天刚刚看到的bug报告。我认为它已在最新版本中修复

    给你:


    它在8.4中解决了这个问题。我想这就是你所描述的

    这对于我的用例非常有用,我有一个简单的对话框,并且没有对应用程序类进行子类化。很好,你试图提供帮助-但这并不能解决OP的问题:没有按钮;)
    public Stage getParentStage() {
        return (Stage) getFxmlNode().getScene().getWindow();
    }
    
    btnCancel.setOnAction(e -> {
        getParentStage().close();
    });
    
    Window window = Main.getPrimaryStage()  // Get the primary stage from your Application class
                    .getScene()
                    .getWindow();
    
    window.fireEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSE_REQUEST));
    
    public Stage getParentStage() {
        return (Stage) getFxmlNode().getScene().getWindow();
    }
    
    btnCancel.setOnAction(e -> {
        getParentStage().close();
    });