JavaFX:阶段关闭处理程序
Posted
技术标签:
【中文标题】JavaFX:阶段关闭处理程序【英文标题】:JavaFX: Stage close handler 【发布时间】:2014-12-24 12:29:54 【问题描述】:我想在关闭我的 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
的处理程序?
【问题讨论】:
【参考方案1】:如果您查看 Application
类的 life-cycle:
JavaFX 运行时按顺序执行以下操作,只要 应用程序启动:
构造指定应用程序类的实例 调用
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()
,您不再需要收听关闭请求来保存文件(但如果您想阻止窗口关闭,您可以这样做)。
【讨论】:
【参考方案2】:假设您想询问用户是否要退出应用程序而不保存工作。如果用户选择 no,则无法避免应用程序在 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));
【讨论】:
对我的用例非常有用,我有一个简单的对话框并且没有继承 Application 类。【参考方案3】:啊,这是 JavaFX 中的一个已知错误,如果在关闭时存在模式对话框,舞台将不会关闭。我会将您链接到我今天刚刚看到的错误报告。我认为它已在最新版本中修复。
给你:
https://bugs.openjdk.java.net/browse/JDK-8093147?jql=text%20~%20%22javafx%20re-entrant%22
它说在 8.4 中解决。我想这就是你所描述的。
【讨论】:
【参考方案4】:public Stage getParentStage()
return (Stage) getFxmlNode().getScene().getWindow();
btnCancel.setOnAction(e ->
getParentStage().close();
);
【讨论】:
很好,您试图提供帮助 - 但这并不能解决 OP 的问题:没有按钮 ;)以上是关于JavaFX:阶段关闭处理程序的主要内容,如果未能解决你的问题,请参考以下文章