【问题标题】:Why am I getting a stackoverflow when loading my fxml?为什么加载我的 fxml 时会出现 stackoverflow?
【发布时间】:2013-12-28 23:46:14
【问题描述】:

我已经调整了我的控制器构造函数和 fxml,以便控制器的所有 fxml 设置都在 fxml 中,除了 FXML 构造和 fxml 加载。这是我的控制器:

public class MainOverviewTab extends Tab {

@FXML private AnchorPane content;

public MainOverviewTab() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("main_overview_tab.fxml"));
    // fxmlLoader.setRoot(content);
    // fxmlLoader.setController(this);      

    try {
        fxmlLoader.load();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

还有我的 fxml 文件:

<AnchorPane id="AnchorPane" 
    fx:id="content" 
    fx:controller="dominion.application.controller.MainOverviewTab"
    ...other settings >

        <children>
            ....
        </children>
</AnchorPane>

当调用 fxmlLoader.load() 并返回 FXMLLoader fxmlLoader = new FXMLLoader(...) 然后再次调用 fxmlLoader.load() 时会发生堆栈溢出...为什么会发生这种情况,我该怎么办保持我的控制器构造函数相同并加载相同的 fxml?或者这不可能?

【问题讨论】:

标签: java javafx javafx-2 fxml


【解决方案1】:

你不应该在构造函数中调用 FXml 加载器。因为当您使用 FXml loader 加载 fxml 文件时,它将一次又一次地递归创建 MainOverviewTab。所以它会导致堆栈溢出错误。如果您从构造函数中删除代码并从显式方法调用,它将起作用。

public static void mainTabLoader() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("main_overview_tab.fxml"));
    // fxmlLoader.setRoot(content);
    // fxmlLoader.setController(this);      

    try {
        fxmlLoader.load();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

【讨论】:

  • 在这种情况下不需要 setRoot 和 setController 调用。
  • 但是当我取消注释 setRoot 和 setController 并且我在 fxml 中删除这些属性时它可以工作。
  • 如果 FXML 中没有 fx:controller 属性,FXMLLoader 的 load(...) 方法将不会实例化控制器。所以删除属性会破坏无限递归。
【解决方案2】:

如果您在 FXMLLoader 实例上调用 setController(...),则不应在 FXML 文件中指定控制器。从 FXML 文件中删除 fx:controller 属性并取消注释 setRoot(...) 和 setController(...) 调用,它应该可以工作。

【讨论】:

  • 但是我在构造函数中注释掉的行是我要删除的。我还想将属性保留在 FXML 文件中,并且我希望所有这些都不会出现异常。
  • 在这种情况下,您应该将 FXML 的加载移出控制器类。通常它会在您的 Application 子类的 start(...) 方法中完成,但如果您使用多个 FXML,它可能会在其他地方完成。 fxmlLoader.load(...) 方法解析 FXML 文件,查看 fx:controller 属性,实例化控制器,并调用其 initialize() 方法。如果您在构造函数(或 initialize() 方法)中使用相同的 FXML 文件调用 fxmlLoader.load(...),最终会导致无限递归。
【解决方案3】:

当控制器构造函数尝试使用 fx:controller 命名它的属性加载 FXML 时会发生这种情况,它会无限递归。去过那里...巧妙地使用 fxmlLoader.setControllerFactory(factoryObject) 可以解决这个问题。

请参阅我的answer,了解在根元素中保留 fx:controller 属性的基于 FXML 的控件,这可以适用于其他控制器的创建。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    • 1970-01-01
    相关资源
    最近更新 更多