JavaFX controller injection does not work

我与影子孤独终老i 提交于 2019-12-20 04:13:01

问题


I have two fxml files. I connect them with an include statement:

The "main" fxmlfile looks like that:

<?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>

And the second one (= "AnotherFile.fxml") like that:

<?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>

Now, I am using injections in the "main"-controller application.MyMainController:

@FXML
private Label oneOfMyLabels;

If I run the controller I get a java.lang.NullPointerException exception, respectively a java.lang.reflect.InvocationTargetException one. In debugging mode I found out, that the injected Label is null!

Now, my question: Can't reach the MyMainController from the "main fxml file" the components of the included fxml file?? Do I have to use an own controller on each fxml file, if it is included or not?!

Thanks for your help!!


回答1:


You need to have a different controller for each FXML file, and the fx:id-annotated elements of each file will be injected into the corresponding controller instance.

When you have included FXML files, you can inject the controller for the included file into the controller for the including file, by setting an fx:id attribute on the fx:include element:

"main" fxml file:

<?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>

and in the "main controller":

public class MyMainController {

    @FXML
    private AnotherController anotherController ;

    // ...
}

(the rule being that the field name is the value of the fx:id attribute with "Controller" appended). Here AnotherController is the controller class for AnotherFile.fxml.

Now you can, for example, expose the data you need to access in the "included controller":

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);
    }

    // ...
}

and then your main controller can do things like

anotherController.setText(...);

which will of course update the label. This preserves encapsulation, so that if you choose to use another control instead of a label, those changes do not have to propagate outside of the immediate controller.



来源:https://stackoverflow.com/questions/32849277/javafx-controller-injection-does-not-work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!