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
。使用:
- 带有
fx:id="buttonLoginRegister"
的按钮转到 REGISTER
场景
- 带有
fx:id="buttonRegisterBack"
的按钮返回到 LOGIN
。
并且都具有相同的 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());
这是错误的。确切地说, fieldRegisterUsername
是 null
.
为什么有些元素是用 lookup(String id)
方法而不是 @FXML
注释找到的?
正如我在评论中提到的,在不同视图之间共享控制器很少是个好主意,我强烈建议您为每个视图创建一个单独的控制器。
至于您的问题本身 - 您有两个控制器实例 class,每次调用一个实例 FXMLLoader.load
。据推测,一个视图具有 fieldLoginUsername
TextField,而另一个具有 fieldRegisterUsername
.
如果满足if
语句的条件,则表示活动场景是登录场景,因此处理它的控制器是具有fieldLoginUsername
的控制器,因此fieldRegisterUsername
自然为空.
但是在 if
子句的第一行中,您将活动场景更改为注册场景,因此当您调用 scene#lookup
时,您指的是控制器为注册场景的场景控制器,确实有 fieldRegisterUsername
的控制器。
如果您在更改活动场景之前调用 scene#lookup
,您会发现它 returns 也为空。
如果您必须对控制器使用相同的 class,您可能需要确保只有一个 实例 class。这将需要使用 FXMLLoader#setController
。
我开始探索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
。使用:
- 带有
fx:id="buttonLoginRegister"
的按钮转到REGISTER
场景 - 带有
fx:id="buttonRegisterBack"
的按钮返回到LOGIN
。
并且都具有相同的 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());
这是错误的。确切地说, fieldRegisterUsername
是 null
.
为什么有些元素是用 lookup(String id)
方法而不是 @FXML
注释找到的?
正如我在评论中提到的,在不同视图之间共享控制器很少是个好主意,我强烈建议您为每个视图创建一个单独的控制器。
至于您的问题本身 - 您有两个控制器实例 class,每次调用一个实例 FXMLLoader.load
。据推测,一个视图具有 fieldLoginUsername
TextField,而另一个具有 fieldRegisterUsername
.
如果满足if
语句的条件,则表示活动场景是登录场景,因此处理它的控制器是具有fieldLoginUsername
的控制器,因此fieldRegisterUsername
自然为空.
但是在 if
子句的第一行中,您将活动场景更改为注册场景,因此当您调用 scene#lookup
时,您指的是控制器为注册场景的场景控制器,确实有 fieldRegisterUsername
的控制器。
如果您在更改活动场景之前调用 scene#lookup
,您会发现它 returns 也为空。
如果您必须对控制器使用相同的 class,您可能需要确保只有一个 实例 class。这将需要使用 FXMLLoader#setController
。