JavaFX 控制器注入不起作用

mrb*_*ela 1 javafx fxml

我有两个fxml文件。我用一个include声明将它们联系起来:

“主”fxml文件如下所示:

<?import javafx.geometry.*?>
// ...

<BorderPane prefHeight="962" prefWidth="1280" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MyMainController">
    <center>
        <SplitPane dividerPositions="0.63" BorderPane.alignment="CENTER">
            <items>
                <fx:include source="AnotherFile.fxml" />
                // ...
            </items>
        </SplitPane>
    </center>
    <top>
        // ...
    </top>
</BorderPane>
Run Code Online (Sandbox Code Playgroud)

第二个(=“AnotherFile.fxml”)就像这样:

<?import java.lang.*?>
// ...

<SplitPane dividerPositions="0.15" orientation="VERTICAL" prefHeight="400.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
    <items>
        // ...
        <Label fx:id="oneOfMyLabels" text="myText" GridPane.columnIndex="2" GridPane.rowIndex="1" />
    </items>
</SplitPane>
Run Code Online (Sandbox Code Playgroud)

现在,我在“主”控制器中使用注入application.MyMainController

@FXML
private Label oneOfMyLabels;
Run Code Online (Sandbox Code Playgroud)

如果我运行控制器,我会得到java.lang.NullPointerException一个异常java.lang.reflect.InvocationTargetException。在调试模式下我发现,注入的Labelnull

现在,我的问题:无法MyMainController从“主 fxml 文件”访问所包含的 fxml 文件的组件?我是否必须在每个 fxml 文件上使用自己的控制器(无论是否包含)?

感谢您的帮助!!

Jam*_*s_D 5

每个 FXML 文件需要有一个不同的控制器,fx:id每个文件的 -annotated 元素将被注入到相应的控制器实例中。

fx:id当您包含 FXML 文件时,您可以通过在元素上设置属性,将包含文件的控制器注入到包含文件的控制器中fx:include

“主”fxml 文件:

<?import javafx.geometry.*?>
// ...

<BorderPane prefHeight="962" prefWidth="1280" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MyMainController">
    <center>
        <SplitPane dividerPositions="0.63" BorderPane.alignment="CENTER">
            <items>
                <fx:include fx:id="another" source="AnotherFile.fxml" />
                // ...
            </items>
        </SplitPane>
    </center>
    <top>
        // ...
    </top>
</BorderPane>
Run Code Online (Sandbox Code Playgroud)

在“主控制器”中:

public class MyMainController {

    @FXML
    private AnotherController anotherController ;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

(规则是字段名称是附加fx:id的属性值"Controller")。这AnotherController是 的控制器类AnotherFile.fxml

例如,现在您可以在“包含的控制器”中公开需要访问的数据:

public class AnotherController {

    @FXML
    private Label oneOfMyLabels ;

    public StringProperty textProperty() {
        return oneOfMyLabels.textProperty();
    }

    public final String getText() {
        return textProperty().get();
    }

    public final setText(String text) {
        textProperty().set(text);
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

然后你的主控制器可以做类似的事情

anotherController.setText(...);
Run Code Online (Sandbox Code Playgroud)

这当然会更新标签。这保留了封装,因此如果您选择使用另一个控件而不是标签,这些更改不必传播到直接控制器之外。