当前位置: 首页 > 知识库问答 >
问题:

如何在初始化期间从控制器获取阶段?

万俟光临
2023-03-14

我想从我的控制器类中处理阶段事件(即隐藏)。所以我所要做的就是添加一个这样的侦听器:

((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中。这一切都以将所需的侦听器设置为阶段事件而结束。

我觉得听众太多了。

这是解决我问题的唯一方法吗?

共有3个答案

龚运乾
2023-03-14

我知道这不是你想要的答案,但在我看来,拟议的解决方案并不好(你自己的方式就是这样)。为什么?因为它们取决于应用程序状态。在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);
...
吕亮
2023-03-14

您只需要给AnchorPane一个ID,然后您就可以从中获取Stage

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

从这里,您可以添加所需的侦听器。

编辑:如EarthMind在下面所述,它不一定是锚烷元素;它可以是您定义的任何元素。

乔伯寅
2023-03-14

初始化后,可以通过getController()从FXMLLoader获取控制器实例,但需要实例化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
 类似资料:
  • 我尝试加载一个FXML,并使用Java代码(而不是使用FXML标记)设置控制器。我在FXML中有不同的字段。我尝试加载(例如文本字段、按钮...)。 下面是一个例子: 如您所见,我创建了一个新的选项卡,为它设置文本,将它添加到tabpane,加载fxml,然后创建一个新的控制器,并将其设置为fxml的控制器。之后,我尝试在初始化之前在fxml中设置一个值,以便在控制器中使用它来更新文本字段或按钮。

  • 问题内容: 我想延迟控制器的初始化,直到从服务器收到必要的数据为止。 我找到了针对Angular1.0.1的解决方案:延迟AngularJS路由更改,直到加载模型以防止闪烁,但无法使其与Angular1.1.0一起使用 模板 ​ JavaScript http://jsfiddle.net/dTJ9N/1/ 问题答案: 由于$ http返回了promise,因此创建自己的deferred仅在htt

  • 问题内容: 如果您有一个控制器来操作Angular.js中的$ scope变量,是否有惯用的方法: 重置控制器的$ scope,然后 重新启动控制器初始化? 对于复杂的控制器,不必将每个变量都重置为其初始值将非常方便,特别是如果您真正想要的是对控制器和范围进行简单的重新初始化。通过再次导航到相同的URL 并没有帮助。 编辑:假设我不能使用任何黑客工具,因为这会违反Chrome打包应用中的CSP。

  • 我怎么绕过这个?我需要以某种方式再次实现那个方法,但突然间我不能通过作为一个论点的阶段。

  • 我正在开发我的第一个 Swing 应用程序,现在提出了一个难题:在静态初始化期间或开始实际执行后执行引导和资源初始化。我是什么意思...我有单例: 因此,方法如下所示 或者,也许我在启动后手动初始化资源,然后运行它。逻辑上正确的方式是什么?

  • null 我在TopMenuButtons中有一个按钮,它具有openAssisstantStage()方法,打开新的小阶段: 对于这个阶段,我还有FXML文件和控制器(AssisstantController)。只有2个按钮-第一个按钮应该打开前一个阶段和关闭电流,但第二个按钮也应该打开普雷沃阶段,关闭电流,也打开一个特定的标签在我的标签视图和做一些其他逻辑例如。获取实际localDate: 我