Reputation: 44456
I start exploring the JavaFX FXML application technology.
I use one main Stage accessed in Main class with Main.getStage()
that is invoked in the start of application with the overriden method public void start(Stage stage)
. Having two public static Scene
inside to keep the persistence while switching them.
@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;
}
Both Scenes have the same controller class called MainController
. Using:
fx:id="buttonLoginRegister"
to go to the REGISTER
Scene fx:id="buttonRegisterBack"
to go back to the LOGIN
one.and both having the same onClick
event handleButtonAction(ActionEvent event)
. The TextFields are fields for a username to log 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();
}
}
My goal is to copy the value from the LOGIN
TextField to the one in the REGISTER
scene. It works well using the code above. However firstly I tried to access the element in the another Scene with:
fieldRegisterUsername.setText(fieldLoginUsername.getText());
And it's erroneous. To be exact, the fieldRegisterUsername
is null
.
Why are some elements found with the lookup(String id)
method and not with @FXML
annotation?
Upvotes: 0
Views: 740
Reputation: 6911
As mentioned in my comment, sharing a controller between different views is rarely a good idea, and I'd strongly advise you to make a separate controller for each view.
As to your problem itself - you have two instances of your controller class, one for each time you call FXMLLoader.load
. Presumably, one view has the fieldLoginUsername
TextField, while the other has fieldRegisterUsername
.
If the condition of the if
statement is met, it means the active scene was the Login scene, thus the controller handling it is the one which has fieldLoginUsername
, so naturally fieldRegisterUsername
will be null.
But on the first line inside the if
clause you change the active scene to the Register one, so by the time you call scene#lookup
you are referring to the scene whose controller is the Register controller, the one that does have fieldRegisterUsername
.
If you were to call scene#lookup
before changing the active scene you would find it returns null as well.
If you must use the same class for controller, you probably want to make sure you only have one instance of that class. That would necessitate using FXMLLoader#setController
.
Upvotes: 2