JavaFX FXML 访问使用 lookup() 方法成功,但使用 @FXML 注释不成功

JavaFX FXML access succeed with lookup() method but not with @FXML annotation

我开始探索JavaFX FXML应用技术

我使用一个在 Main class 中访问的主阶段,其中 Main.getStage() 在应用程序启动时使用覆盖方法 public void start(Stage stage) 调用。内部有两个 public static Scene 以在切换它们时保持持久性。

@Override
public void start(Stage stage) throws Exception {
    STAGE = stage;
    LOGIN = new Scene(FXMLLoader.load(getClass().getResource("Login.fxml")));
    REGISTER = new Scene(FXMLLoader.load(getClass().getResource("Register.fxml")));

    STAGE.setScene(LOGIN);
    STAGE.setTitle("FXApplication");
    STAGE.show();
}

public static Stage getStage() {
    return STAGE;
}

两个场景都有相同的控制器 class,名为 MainController。使用:

并且都具有相同的 onClick 事件 handleButtonAction(ActionEvent event)。 TextFields 是用于记录用户名的字段 in/register.

@FXML private Button buttonLoginRegister;
@FXML private Button buttonRegisterBack;
@FXML private TextField fieldLoginUsername;
@FXML private TextField fieldRegisterUsername;

@FXML
private void handleButtonAction(ActionEvent event) throws IOException {

    Stage stage = Main.getStage();

    if (event.getSource() == buttonLoginRegister) {     
        stage.setScene(Main.REGISTER);
        stage.show();

        // Setting the text, the working way
        TextField node = (TextField) stage.getScene().lookup("#fieldRegisterUsername");
        node.setText(fieldLoginUsername.getText());

        // Setting the text, the erroneous way
        // fieldRegisterUsername.setText(fieldLoginUsername.getText());

    } else {
        stage.setScene(Main.LOGIN);
        stage.show();
    }
}

我的目标是将值从 LOGIN TextField 复制到 REGISTER 场景中的值。使用上面的代码效果很好。但是首先我尝试访问另一个场景中的元素:

fieldRegisterUsername.setText(fieldLoginUsername.getText());

这是错误的。确切地说, fieldRegisterUsernamenull.

为什么有些元素是用 lookup(String id) 方法而不是 @FXML 注释找到的?

正如我在评论中提到的,在不同视图之间共享控制器很少是个好主意,我强烈建议您为每个视图创建一个单独的控制器。

至于您的问题本身 - 您有两个控制器实例 class,每次调用一个实例 FXMLLoader.load。据推测,一个视图具有 fieldLoginUsername TextField,而另一个具有 fieldRegisterUsername.
如果满足if语句的条件,则表示活动场景是登录场景,因此处理它的控制器是具有fieldLoginUsername的控制器,因此fieldRegisterUsername自然为空.

但是在 if 子句的第一行中,您将活动场景更改为注册场景,因此当您调用 scene#lookup 时,您指的是控制器为注册场景的场景控制器,确实有 fieldRegisterUsername 的控制器。

如果您在更改活动场景之前调用 scene#lookup,您会发现它 returns 也为空。

如果您必须对控制器使用相同的 class,您可能需要确保只有一个 实例 class。这将需要使用 FXMLLoader#setController