我开始探索 JavaFX FXML 应用程序技术。
我使用在 Main 类中通过 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;
}
两个场景都有相同的 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());
这是错误的。确切地说,fieldRegisterUsername
为 null
。
为什么使用 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/