JavaFX的:如何在初始化过程中得到控制的阶段?(JavaFX: How to get stage

2019-06-18 21:36发布

我想从我的控制器类处理阶段事件(即隐藏)。 因此,所有我需要做的就是通过添加一个监听器

((Stage)myPane.getScene().getWindow()).setOn*whatIwant*(...);

但问题是,初始化之后立即开始

Parent root = FXMLLoader.load(getClass().getResource("MyGui.fxml"));

和之前

Scene scene = new Scene(root);
stage.setScene(scene);

因而.getScene()返回null。

我发现我自己唯一的解决方法是添加一个侦听myPane.sceneProperty(),当它变得不空,我得到的场景,加入到它的.windowProperty()我!该死! 听者处理,我终于找回阶段。 而这一切都与设定所需的听众舞台活动结束。 我觉得有太多的听众。 它是解决我的问题的唯一途径?

Answer 1:

你可以从控制器的实例FXMLLoader通过初始化后getController()但你需要实例化一个FXMLLoader而是采用静态方法即可。

我打完电话后传递阶段load()后直接到控制器:

FXMLLoader loader = new FXMLLoader(getClass().getResource("MyGui.fxml"));
Parent root = (Parent)loader.load();
MyController controller = (MyController)loader.getController();
controller.setStageAndSetupListeners(stage); // or what you want to do


Answer 2:

所有你需要的是给AnchorPane一个ID,然后就可以拿到Stage从。

@FXML private AnchorPane ap;
Stage stage = (Stage) ap.getScene().getWindow();

在这里,您可以在添加Listener ,你所需要的。

编辑:正如由下面EarthMind说明,它并不必须是AnchorPane元件; 它可以是你定义的任何元素。



Answer 3:

我知道这不是你想要的答案,但IMO提出的解决方案都不好(和你自己的方式是)。 为什么? 因为它们所依赖的应用程序的状态。 在JavaFX,控制,场景和阶段不依赖于对方。 这意味着控制生活中可以没有被添加到场景和场景可以在不被附着到阶段存在。 然后,在t1时刻,能够控制得到重视的场景,并在t2时刻,那场面可被添加到一个阶段(这解释了为什么他们是彼此的可观察性)。

这样建议得到控制器参考,并调用一个方法,将阶段它的方式增加了一个状态到您的应用程序。 这意味着你需要调用该方法在适当的时候,在创建阶段之后。 换句话说,你现在需要遵循的顺序:1-通过一种方法创建阶段2 - 通过这个创建阶段到控制器。

你不能(或不应该)在这种方法中改变这个顺序。 所以,你失去了无国籍。 而在软件,通常,国家是邪恶的。 理想情况下,方法应不需要任何来电订购。

那么,什么是正确的解决方案? 有两种选择:

1 - 你的方法,在控制器听属性来获取阶段。 我认为这是正确的做法。 像这样:

pane.sceneProperty().addListener((observableScene, oldScene, newScene) -> {
    if (oldScene == null && newScene != null) {
        // scene is set for the first time. Now its the time to listen stage changes.
        newScene.windowProperty().addListener((observableWindow, oldWindow, newWindow) -> {
            if (oldWindow == null && newWindow != null) {
                // stage is set. now is the right time to do whatever we need to the stage in the controller.
                ((Stage) newWindow).maximizedProperty().addListener((a, b, c) -> {
                    if (c) {
                        System.out.println("I am maximized!");
                    }
                });
            }
        });
    }
});

2-你做你需要做的,你创造了什么Stage (这不是你想要的):

Stage stage = new Stage();
stage.maximizedProperty().addListener((a, b, c) -> {
            if (c) {
                System.out.println("I am maximized!");
            }
        });
stage.setScene(someScene);
...


Answer 4:

最简单的办法让舞台对象控制器是:

  1. 添加一个额外的方法一样(这将是一个setter方法来设置控制器类的阶段)创建自己的控制器类,

     private Stage myStage; public void setStage(Stage stage) { myStage = stage; } 
  2. 获取启动方法控制和设定阶段

     FXMLLoader loader = new FXMLLoader(getClass().getResource("MyFXML.fxml")); OwnController controller = loader.getController(); controller.setStage(this.stage); 
  3. 现在,您可以访问阶段控制器



Answer 5:

分配FX:ID或声明变量到任何节点的/:anchorpane,按钮等,然后事件处理程序添加到它与该事件处理程序中插入下面给定的代码:

Stage stage = (Stage)((Node)((EventObject) eventVariable).getSource()).getScene().getWindow();

希望,这对你的作品!



Answer 6:

你可以得到node.getScene ,如果你不从调用Platform.runLater ,结果是空值。

例如空值:

node.getScene();

例如,没有空值:

Platform.runLater(() -> {
    node.getScene().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
               //your event
     });
});


文章来源: JavaFX: How to get stage from controller during initialization?