在 start 方法中与 FXML 元素交互时如何修复 NullPointerException?

How can I fix a NullPointerException when interacting with FXML elements in the start method?

我正在编写一些代码,通过 start 方法与 FXML 元素交互(更改文本)。但是,我发现当我从我的控制器 class 调用该方法时,我得到了 NullPointerException。我发现这个问题与线程有关,但我已经能够使任何东西正常工作。我已经包含了一些生成相同问题的示例代码。

主要class:

public class Main extends Application {
    Controller C = new Controller();

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        Scene scene = new Scene(root, 300, 275);
        stage.setTitle("FXML Welcome");
        stage.setScene(scene);
        stage.show();
        C.handleSubmitButtonAction();//Error happens here.
    }

    public static void main(String[] args) {
        launch(args);
    }
}

控制器class:

public class Controller{
    @FXML public Text actiontarget;

    @FXML protected void handleSubmitButtonAction() {
        actiontarget.setText("Sign in button pressed");
    }
}

FXML 代码:

<GridPane fx:id="GridPane" fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
    <children>
        <Text text="Welcome" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="2"/>
        <Label text="User Name:" GridPane.columnIndex="0" GridPane.rowIndex="1"/>
        <TextField GridPane.columnIndex="1" GridPane.rowIndex="1"/>
        <Label text="Password:" GridPane.columnIndex="0" GridPane.rowIndex="2"/>
        <PasswordField fx:id="passwordField" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
        <HBox spacing="10" alignment="bottom_right" GridPane.columnIndex="1" GridPane.rowIndex="4">
            <Button text="Sign In" onAction="#handleSubmitButtonAction"/>
        </HBox>
        <Text fx:id="actiontarget" GridPane.columnIndex="1" GridPane.rowIndex="6"/>
    </children>
</GridPane>

如果您使用 fxml 中的 fx:controller 属性指定控制器 class,FXMLLoader 会创建控制器本身的实例。

要访问该实例,您需要创建一个 FXMLLoader 实例 并在加载 fxml 后使用 getController()。否则,注入值的控制器实例与您自己创建并存储在 C 字段中的控制器实例不同:

FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"))
Parent root = loader.load();
C = loader.getController();