在 FXML 文件中多次插入相同的对象 (JavaFX)

Insert the same object several times in FXML file (JavaFX)

我有一个包含 2 个选项卡的 FXML 文件。在每个选项卡中,我都有相同的 Text 元素列表。如何避免重复每个 Text 元素?

这是我的 FXML 文件的摘录:

<Tab>
    <GridPane>
        <columnConstraints>
            <ColumnConstraints />
        </columnConstraints>
        <rowConstraints>
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
        <RowConstraints />
        </rowConstraints>
        <children>
            <Text fx:id="text1" GridPane.rowIndex="1" />
            <Text fx:id="text2" GridPane.rowIndex="2" />
            <Text fx:id="text3" GridPane.rowIndex="3" />
            <Text fx:id="text4" GridPane.rowIndex="4" />
        </children>
    </GridPane>
</Tab>
<Tab>
    <GridPane>
        <columnConstraints>
            <ColumnConstraints />
        </columnConstraints>
        <rowConstraints>
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
        <RowConstraints />
        </rowConstraints>
        <children>
            <Text fx:id="text1" GridPane.rowIndex="1" />
            <Text fx:id="text2" GridPane.rowIndex="2" />
            <Text fx:id="text3" GridPane.rowIndex="3" />
            <Text fx:id="text4" GridPane.rowIndex="4" />
        </children>
    </GridPane>
</Tab>

如果我在两个Text元素中放置相同的id(例如:在两个选项卡中放置fx:id="text1"),我会出错(Duplicate id reference)。

是的,每个组件都必须具有唯一的 fx:id 值。您应该将第二个重命名为 text11text12... 之类的名称。

可以使用 fx:include 和嵌套控制器重写 fxml。


创建一个新的 fxml 文件sub.fxml,其中包含您重复的场景部分,例如

<Tab xmlns:fx="http://javafx.com/fxml/1" fx:controller="mypackage.SubController">
    <GridPane>
        <columnConstraints>
            <ColumnConstraints />
        </columnConstraints>
        <rowConstraints>
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
        <RowConstraints />
        </rowConstraints>
        <children>
            <Text fx:id="text1" GridPane.rowIndex="1" />
            <Text fx:id="text2" GridPane.rowIndex="2" />
            <Text fx:id="text3" GridPane.rowIndex="3" />
            <Text fx:id="text4" GridPane.rowIndex="4" />
        </children>
    </GridPane>
</Tab>

创建 SubController class 并使相关部分可访问:

public class SubController {
    @FXML
    private Text text1;
    ...
    @FXML
    private Text text4;

    public void setText1(String text) {
        this.text1.setText(text);
    }

    ...
}

现在更改 "main" fxml 以使用包含的 fxml:

<fx:include source="sub.fxml" fx:id="tab1" />
<fx:include source="sub.fxml" fx:id="tab2" />

并在父控制器中创建用于注入 SubControllers 的字段:

@FXML
private SubController tab1Controller;
@FXML
private SubController tab2Controller;

您将能够像访问其他注入元素一样访问控制器。例如。在第一个 Tab:

中设置 text1 的文本
tab1Controller.setText1("Hello World!");

好的,我基于 解释了如何从 Java 代码加载项目。如果我加载同一个项目 2 次(一次在第一个选项卡中,第二次在第二个选项卡中),它只会显示在第二个选项卡上......所以一个项目只能显示一次。所以我只创建了 2 个相同的项目。

这是我的 FXML 代码的一部分:

<Tab>
    <GridPane>
        <columnConstraints>
            <ColumnConstraints />
        </columnConstraints>
        <rowConstraints>
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
        <RowConstraints />
        </rowConstraints>
        <children>
            <!-- I add my Text elements from JavaFX code -->
        </children>
    </GridPane>
</Tab>
<Tab>
    <GridPane>
        <columnConstraints>
            <ColumnConstraints />
        </columnConstraints>
        <rowConstraints>
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
            <RowConstraints />
        <RowConstraints />
        </rowConstraints>
        <children>
            <!-- I add my Text elements from JavaFX code -->
        </children>
    </GridPane>
</Tab>

这是我的 Java 代码的一部分:

@FXML private GridPane gridPaneFirstTab;
@FXML private GridPane gridPaneSecondTab;

private List<Text> textCallbacksList1 = new ArrayList<>();
private List<Text> textCallbacksList2 = new ArrayList<>();
private final List<String> callbackNames = Arrays.asList(
    "text1",
    "text2",
    "text3"
);

Text text1, text2;
for (int i = 0; i < callbackNames.size(); ++i) {
    text1 = new Text(MessagesBundle.getString(callbackNames.get(i)));
    text2 = new Text(MessagesBundle.getString(callbackNames.get(i)));
    textCallbacksList1.add(text1);
    textCallbacksList2.add(text1);

    gridPaneFirstTab.getChildren().add(text1);
    gridPaneSecondTab.getChildren().add(text2);

    gridPaneFirstTab.setConstraints(text1, 0, i + 1);
    gridPaneSecondTab.setConstraints(text2, 0, i + 1);
}