首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >访问自定义FXML组件Init中的子组件

访问自定义FXML组件Init中的子组件
EN

Stack Overflow用户
提问于 2020-02-07 03:00:07
回答 1查看 205关注 0票数 0

如果我有这样的自定义JavaFX组件(例如):

代码语言:javascript
运行
复制
public class MenuWidget extends VBox implements Initializable {
    @FXML
    StackPane menus;

    public MenuWidget() {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/resources/MenuWidget.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        System.out.println(menus.getChildren().size());
    }
}

使用此FXML:

代码语言:javascript
运行
复制
<fx:root type="javafx.scene.layout.VBox" prefWidth="300.0" xmlns:fx="http://javafx.com/fxml/1">
    <StackPane fx:id="menus">
        <padding>
            <Insets top="5" left="5" bottom="5" right="5"></Insets>
        </padding>
    </StackPane>    
</fx:root>

我在另一个FXML文件中使用这样的自定义组件:

代码语言:javascript
运行
复制
<MenuWidget>
    <menus>
        <fx:include source="FirstMenu.fxml" />
        <fx:include source="SecondMenu.fxml" />
    </menus>            
</MenuWidget>

为什么MenuWidget中的Initialize()方法要打印0?本质上,在构造MenuWidget时,我需要访问堆栈窗格的子元素,这样我就可以设置顶级菜单的其他菜单控件(我已经从本例中删除了该控件)。在调用init方法之前,FXMLLoader不应该用它的所有属性填充控制器( MenuWidget)吗?

编辑:知道init是在构造函数完成之前调用的,所以尝试将init代码移动到构造函数中(在fmxmlLoader.load()调用之后),但它仍然无法工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-07 03:53:57

MenuWidget类及其关联的FXML文件是完全独立的。您没有包含任何内容,也没有将任何子元素添加到StackPane中。换言之,这是:

代码语言:javascript
运行
复制
public class MenuWidget extends VBox implements Initializable {
    @FXML
    StackPane menus;

    public MenuWidget() {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/resources/MenuWidget.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        System.out.println(menus.getChildren().size());
    }
}

加载以下内容:

代码语言:javascript
运行
复制
<fx:root type="javafx.scene.layout.VBox" prefWidth="300.0" xmlns:fx="http://javafx.com/fxml/1">
    <StackPane fx:id="menus">
        <padding>
            <Insets top="5" left="5" bottom="5" right="5"></Insets>
        </padding>
    </StackPane>    
</fx:root>

一旦完成该操作,就会调用initialize方法。在menus中没有添加任何内容,因此调用menus.getChildren().size()的结果当然是0

在其他地方,您正在加载以下内容:

代码语言:javascript
运行
复制
<MenuWidget>
    <menus>
        <fx:include source="FirstMenu.fxml" />
        <fx:include source="SecondMenu.fxml" />
    </menus>            
</MenuWidget>

这将导致MenuWidget被实例化,这涉及调用MenuWidget#initialize方法,,然后尝试将子元素添加到menus。换句话说,如果这是有效且工作的FXML,那么在创建和初始化实例之后,将添加MenuWidget子实例。

但是,<menus>元素应该会导致应用程序抛出异常。MenuWidget类没有定义名为menus只读列表属性。如果要使用<menus>,并且希望将该列表中的元素添加到menus堆栈窗格的子级,则将MenuWidget类修改为:

代码语言:javascript
运行
复制
public class MenuWidget extends VBox implements Initializable {
    @FXML
    StackPane menus;

    public MenuWidget() {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/resources/MenuWidget.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        System.out.println(menus.getChildren().size());
    }

    // add read-only list property (the "property" is read-only, not 
    // the list itself) named "menus"
    public final ObservableList<Node> getMenus() {
        return menus.getChildren();
    }
}

但这似乎在概念上是错误的(至少对我来说是这样)。我不太清楚您想要做什么,但也许您应该将fx:include-ing其他FXML文件直接放到MenuWidget FXML文件中,而不是您当前正在做的事情。这样,您就可以将控制器和/或视图(参见嵌套控制器)注入到MenuWidget类中。根据您向我们展示的内容,我也不确定在本例中是否完全有理由使用fx:root。从VBox继承似乎并没有给您的代码添加任何好处(也就是说,您没有添加任何功能),因为您只是向它添加一个子(然后向该子子程序添加子)。也许一个标准的FXML文件+控制器会更合适。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60106519

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档