java关闭stage_关于java:JavaFX:阶段关闭处理程序

我想在关闭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类的生命周期:

The JavaFX runtime does the following, in order, whenever an

application is launched:

Constructs an instance of the specified Application class

Calls the init() method

Calls the start(javafx.stage.Stage) method

Waits for the application to finish, which happens when either of the following occur:

the application calls Platform.exit()

the last window has been closed and the implicitExit attribute on Platform is true

Calls the stop() method

这意味着您可以在控制器上调用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 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));

对于我的用例,它非常有用,在这里我有一个简单的对话框,而不是对Application类进行子类化。

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

干得好:

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

它在8.4中解决。我认为这就是您所描述的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值