JavaFX FXML 访问通过 Lookup() 方法成功,但通过 @FXML 注释失败

标签 java javafx fxml

我开始探索 JavaFX FXML 应用程序技术。

我使用在 Main 类中通过 Main.getStage() 访问的一个主阶段,该阶段在应用程序启动时使用重写方法 public void start(Stage stage) 进行调用>。内部有两个 public static Sc​​ene 以在切换它们时保持持久性。

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

两个场景都有相同的 Controller 类,称为MainController。使用:

  • 带有 fx:id="buttonLoginRegister" 的按钮,用于转到 REGISTER 场景
  • 带有 fx:id="buttonRegisterBack" 的按钮,用于返回到 LOGIN 按钮。

并且两者具有相同的onClick事件handleButtonAction(ActionEvent event)。文本字段是用于登录/注册的用户名字段。

@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 注释找到了某些元素?

最佳答案

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

至于您的问题本身 - 您有两个 Controller 类实例,每次调用 FXMLLoader.load 时都有一个实例。据推测,一个 View 具有 fieldLoginUsername TextField,而另一个 View 具有 fieldRegisterUsername
如果满足 if 语句的条件,则意味着 Activity 场景是登录场景,因此处理它的 Controller 是具有 fieldLoginUsername 的 Controller ,所以自然 fieldRegisterUsername 将为空。

但是在 if 子句中的第一行,您将 Activity 场景更改为 Register 场景,因此当您调用 scene#lookup 时,您引用的是其 Controller 是 Register Controller 的场景,该 Controller 具有 fieldRegisterUsername

如果您在更改 Activity 场景之前调用 scene#lookup,您会发现它也会返回 null。

如果您必须为 Controller 使用相同的类,您可能需要确保该类只有一个实例。这就需要使用 FXMLLoader#setController

关于JavaFX FXML 访问通过 Lookup() 方法成功,但通过 @FXML 注释失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37776747/

相关文章:

JavaFX - ListView 不填充 fxml 中的数据

java - 一个 FXML 文件的多个 Controller

java - ChangeListener 不适用于 JSlider

java - 使用 Gson 将 Json 解析为具有通用字段的项目列表

java - Maven 和 Java 扩展

java - 将数据从 map 添加到 Java FX ListView?

java - 将 VLCJ 媒体播放器添加到 JavaFX 中的 Canvas

java - 录音在 Java 中不起作用

java - 当通过屏障(例如 CyclicBarrier)的线程数量小于屏障限制时,屏障(例如 CyclicBarrier)是否会导致死锁?

java - 将jar转换为exe launch4j后出现JNI错误