javaFx:stage如何正确关闭?

2019-05-11  本文已影响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的诡异状态中。

上一篇 下一篇

猜你喜欢

热点阅读