美文网首页
javaFx:stage如何正确关闭?

javaFx:stage如何正确关闭?

作者: 李浩蓝 | 来源:发表于2019-05-11 09:57 被阅读0次

    javaFx:stage如何正确关闭?stage.close()后发生了什么?

    前言:stage.close()官方文档的说明其作用相当于stage.hide(),方法执行后stage并没有被正确关闭,如何才能正确关闭stage呢?下面建立一测试项目来探索一番。

    一、建立项目msd,内有文件:

    (一)、Msd.java  应用程序入口类;

    (二)、javaFx控制器类 FXMLDocumentController.java

    (三)、FXMLDocument.fxml、HtmlEdit.fxml 是视图文件。

    FXMLDocument.fxml定义了一个按钮,HtmlEdit.fxml定义了一个html编辑器。当程序启动时装载FXMLDocument.fxml,点击其中的按钮实现页面跳转到HtmlEdit.fxml并进入全屏模式,按下ctrl+k退出全屏。再次点击按钮一次循环。

    二、JavaFx控制器类 FXMLDocumentController.java实现事件消息的监听控制。

    (一)、该控制器类实现了(implements)Initializable接口方法:public void initialize(URL url, ResourceBundle rb) {},声明并实例化

    private final Stage stageTwo = new Stage();作为全局变量,

    (二)、定义了事件消息处理器方法: private void handleButtonAction(ActionEvent event){},并调用loadFXML("HtmlEdit.fxml", stageTwo);实现页面的切换;

    (三)、loadFXML()方法:装载第二个页面HtmlEdit.fxml并进入全屏模式,附上代码解析如下:

    public AnchorPane loadFXML(String fxmlFileName, Stage stage) {

            //工具方法:载入任意的FXML文件,并切换

            if (fxmlFileName == null || fxmlFileName.isEmpty() || !fxmlFileName.endsWith(".fxml")) {

                return null;

            }

            //单例模式:只能装载1次,直到关闭。

            if (stage != null) {

                if (stage.getScene() != null) {

                    if (stage.getScene().getUserData().toString().equals("showing")) {

                        if (!stage.isShowing()) {

                          //下面这条语句的作用是设置全屏模式退出的组合键

                            stage.setFullScreenExitKeyCombination(KeyCombination.valueOf("Ctrl+K"));

                            //下面这条语句的作用是设置全屏模式进入后在屏幕的提示

                            stage.setFullScreenExitHint("进入了全屏模式....");

                            //下面这条语句的作用是使stage进入全屏模式

                            stage.setFullScreen(true);

                            stage.show();

                        }

                        return (AnchorPane) stage.getScene().getRoot();

                    }

                }

            }

            AnchorPane pane = null;

            try {

                pane = (AnchorPane) FXMLLoader.load(getClass().getResource(fxmlFileName));

            } catch (IOException ex) {

                Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);

            }

            if (pane != null && stage != null) {

                Scene scene = new Scene(pane);

                scene.setUserData("showing");

                stage.setScene(scene);

                stage.show();

                //监听舞台关闭事件:

                stage.setOnCloseRequest((WindowEvent event) -> {

                    System.out.println("stage is hidded and then closed!");   

                    stage.close();//注意!相当于stage.hide(),舞台并没有销毁。

                    //npe:  System.out.println(stage.getUserData().toString());

                });

                //监听舞台隐藏事件(关闭按钮被点击默认是隐藏效果,同上)

                stage.setOnHidden((WindowEvent event) -> {

                    System.out.println("stage hidded! ");

                    //npe: 因为onCloseRequest优先被执行了,stage.close()  stage.getUserData().toString()

                });

                //监听舞台正在被隐藏,尚未隐藏完毕事件。优先于setOnHidded()

                stage.setOnHiding((WindowEvent event) -> {

                    System.out.println("stage is hidding....");

                });

                //监听舞台正准备显示出来事件

                stage.setOnShowing((WindowEvent event) -> {

                    System.out.println("stage is showing...");

                });

                //监听舞台显示完毕事件

                stage.setOnShown((WindowEvent event) -> {

                    System.out.println("stage is showed now!");

                });

                stage.setFullScreenExitKeyCombination(KeyCombination.valueOf("Ctrl+K"));

                stage.setFullScreenExitHint("进入了....");

                stage.setFullScreen(true);

            }

            return pane;

        }

    三、问题

    当stage进入全屏模式,按下ctrl+k退出后,“关闭”stage,再次点击按钮程序工作“正常”,但仔细研究就会发现,当我们将调用stage.close()将stage关闭后:

    (一)、再次引用stage将会抛出NPE异常,说明stage已经被置为null引用。             

                   stage.close();//注意!相当于stage.hide(),舞台并没有销毁。

                    //npe:  System.out.println(stage.getUserData().toString());

    (二)、再次点击按钮,却发现stage还在,以下代码被执行:

    //单例模式:只能装载1次,直到关闭。

            if (stage != null) {   //注意这里!stage在第一次被close()后,再引用会抛出NPE;但是第二次点击按钮它却不是null

                if (stage.getScene() != null) {

                    if (stage.getScene().getUserData().toString().equals("showing")) {

                        if (!stage.isShowing()) {

                            stage.setFullScreenExitKeyCombination(KeyCombination.valueOf("Ctrl+K"));

                            stage.setFullScreenExitHint("进入了....");

                            stage.setFullScreen(true);

                            stage.show();

                        }

                        return (AnchorPane) stage.getScene().getRoot();

                    }

                }

            }

    而stage只是被实例化了一次,作为全局变量使用。当stage.close()调用后,stage并没有被真的销毁,照说应该会被垃圾回收器回收,然而结果还是没有被回收内存没有释放,对stage的引用却处于既是null又是非null的诡异状态中。

    相关文章

      网友评论

          本文标题:javaFx:stage如何正确关闭?

          本文链接:https://www.haomeiwen.com/subject/shvtaqtx.html