相关文章推荐
文雅的数据线  ·  ionic ...·  1 年前    · 
傻傻的甘蔗  ·  encoding - Android ...·  1 年前    · 
欢乐的领带  ·  agentloadexception ...·  1 年前    · 

(一)、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的诡异状态中。