patternjavaMinor
JavaFX FXML/window switcher
Viewed 0 times
switcherfxmlwindowjavafx
Problem
I would like to write simple application where I'm going to make a few views:
I think that my method is not the best way to do this. Can someone give me a tip?
Main.java
Controller.java
```
package application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Controller implements Initializable{
@FXML
Button openRegister;
@FXML
Button openLogin;
private Stage stage;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
@FXML
private void openRegister() throws IOException{
stage = (Stage) openRegister.getScene().getWindow();
BorderPane root;
root = (BorderPane) FXMLLoader.load(getClass().getResource("Register.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
stage.setScene(scene);
System.out.printl
- Login
- Register
- Main app
I think that my method is not the best way to do this. Can someone give me a tip?
Main.java
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("Login.fxml"));
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}Controller.java
```
package application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Controller implements Initializable{
@FXML
Button openRegister;
@FXML
Button openLogin;
private Stage stage;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
@FXML
private void openRegister() throws IOException{
stage = (Stage) openRegister.getScene().getWindow();
BorderPane root;
root = (BorderPane) FXMLLoader.load(getClass().getResource("Register.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
stage.setScene(scene);
System.out.printl
Solution
I think you are on the right track, there are only a few things I would change.
Depending on how your app is going to to be structured, you'll likely want a
UPDATE
I generally make use of an abstract base controller that exposes the different methods I use (
- I would create a static function in the controller which inflates and returns a root node to be added to the stage (or even launches a new stage).
- I would make a separate controller for each window/fragment you want to create. So you would have a
LoginControllerand aRegisterController, each inflating and binding to their respective fxml files.
Depending on how your app is going to to be structured, you'll likely want a
MainController which provides a container to swap sub-controllers in and out of. In this way, each controller is a single entity that can be used ad-hoc; only the main controller will be aware of their existence and be responsible for displaying them. MainController would also provide the ideal place for global menus, titles, toolbar, tabs, etc.UPDATE
public static LoginUiController initScene(Stage stage) throws IOException
{
LoginUiController controller = new LoginUiController();
// Inflate FXML
FXMLLoader loader = new FXMLLoader(LoginUiController.class.getResource("controller/login/Login.fxml"));
loader.setController(controller);
controller.root = loader.load(); // Good to have a pointer to the root node so the controller can be nested
// Create scene
Scene scene = new Scene(controller.root);
stage.setScene(scene);
controller.onCreated(); // Method to let the controller know it has been inflated and added to a scene
return controller;
}I generally make use of an abstract base controller that exposes the different methods I use (
inflateFxml, initScene, onCreate) as well as a property binder lookup table, so the controller can unbind all listeners when closed.Code Snippets
public static LoginUiController initScene(Stage stage) throws IOException
{
LoginUiController controller = new LoginUiController();
// Inflate FXML
FXMLLoader loader = new FXMLLoader(LoginUiController.class.getResource("controller/login/Login.fxml"));
loader.setController(controller);
controller.root = loader.load(); // Good to have a pointer to the root node so the controller can be nested
// Create scene
Scene scene = new Scene(controller.root);
stage.setScene(scene);
controller.onCreated(); // Method to let the controller know it has been inflated and added to a scene
return controller;
}Context
StackExchange Code Review Q#119418, answer score: 4
Revisions (0)
No revisions yet.