Ive created an Login-System which is connected to a SQLite database. After the User entered his correct account informations, a the dashboard should be loaded with his name and balance which should also be retrieved from the database. I created an Account-Objekt from the informations passed into the Login-Form and saved them using the "stage.setUserData()" - Method to use them in the Dashboard-Controller Class.
@FXML
void loginButtonClicked(ActionEvent event) {
String user = usernameTextField.getText();
String pw = passwordTextField.getText();
database.openConnection();
try {
if(loginModel.isLogin(database.getConnection(), user, pw)) {
TabPane root = FXMLLoader.load(getClass().getClassLoader().getResource("de/hannes/account/AccountGUI.fxml"));
final Node source = (Node) event.getSource();
Account account = accModel.getAccount(database.getConnection(), database.getStatement(), user);
stage = (Stage) source.getScene().getWindow();
stage.setUserData(account);
Scene scene = new Scene(root);
stage.setResizable(false);
stage.setTitle("Dashboard");
stage.setScene(scene);
stage.show();
}
else {
usernameTextField.clear();
passwordTextField.clear();
loginButton.setDisable(true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Well, so far it works but only if the user clicks on a Button in the Dashboard and then using the stage.getUserData()" - Method.
@FXML
void test(ActionEvent event) {
Node node = (Node) event.getSource();
Stage stage = (Stage) node.getScene().getWindow();
Account account = (Account) stage.getUserData();
balanceLabel.setText(account.getGuthabenAsString());
}
But that solution is very cumbersome and not user friendly at all. I want to display the users Account-Details without the need to call an Eventhandler on a Button before. I considered using the initialize-Method but I´m not sure how to access the userData without an eventHandler.
While it's possible to use the userData
property of the Stage
, I recommend a different approach. Create a method in the FXML's controller class that you can call. This method would be responsible for performing any additional initialization needed by the controller which can only be done once it has access to an Account
.
// create an FXMLLoader *instance*
FXMLLoader loader = new FXMLLoader(getClass().getResource("/de/hannes/account/AccountGUI.fxml"));
TabPane root = loader.load(); // uses the INSTANCE 'load()' method
YourControllerClass controller = loader.getController(); // called AFTER 'load()'
Account account = accModel.getAccount(database.getConnection(), database.getStatement(), user);
controller.initAccount(account); // call the method you added to the controller
final Node source = (Node) event.getSource();
stage = (Stage) source.getScene().getWindow();
Scene scene = new Scene(root);
stage.setResizable(false);
stage.setTitle("Dashboard");
stage.setScene(scene);
stage.show();
Though note a more appropriate MVC or other architecture would be better here. I see you do have some model classes, which is good, but which account is currently logged in should really be tracked in the model. Then the "account view" can simply query the model for that information rather than being given an Account
directly. That said, you would likely still need to do something similar to the above in order to pass the needed model instance between controllers.
Also, it's strange that acc.getModel(...)
needs to be given (what I assume is) a JDBC Connection
and Statement
as arguments. Similar strangeness with the loginModel
object. The fact a SQL database is being used is an implementation detail. The method signatures should not expose such details. At most, the constructor of the model class should accept a Connection
(though having another class that manages the Connection
might be warranted). Then the methods make use of that Connection
internally.
I should also point out that you're performing database access operations on the JavaFX Application Thread. Or, if not, then you're blocking the FX thread while the database operations complete on a background thread. Either is bad. All database operations and other I/O operations should be performed on a background thread, and the FX thread must remain free to do its job. See Concurrency in JavaFX for more information.