I am trying to open a new window. Specifying the controller programmatically.
OverviewController overviewController = new OverviewController();
final FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("overview.fxml"));
loader.setController(overviewController);
Parent root = loader.getRoot(); // Gives me a "Root cannot be null" error...
Stage stage = new Stage();
Scene scene = new Scene(root);
stage.setTitle("FXML Welcome");
stage.setScene(scene);
stage.setResizable(false);
stage.show();
So it goes wrong after loading the root.
The following code does work, but i want to specify my own controller in the code.
Parent root = null;
try {
root = FXMLLoader.load(getClass().getClassLoader().getResource("overview.fxml"));
Stage stage = new Stage();
Scene scene = new Scene(root);
stage.setTitle("FXML Welcome");
stage.setScene(scene);
stage.setResizable(false);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
The reason getRoot() is returning null is that you haven't actually loaded the FXML file. You need:
loader.load();
Parent root = loader.getRoot();
or, more simply,
Parent root = loader.load();
You have to loader.setRoot() in case you use a dynamic root, <fx:root type="..."> …
And as #James_D pointed out, you have not loaded the fxml file…
Related
Hello I am having an JavaFX app with few controllers and I have 2 options to get back to previous screen. User can click button 'leave' or after finishing some tasks on this screen will be moved to previous automatically. I have problem here because I've created method wiut fxml annotation which takes ActionEvent object as parameter and is called when user click button and when user will finish tasks and should be moved automatically to previous screen I cannot call this method because I dont this object, it's created when an action - click in this case is made. How can I make it possible for both 'exit' options?
So here is my method which is used 'onAction' for my button:
#FXML
private void leaveRoomAction(ActionEvent event) {
try {
removePlayerFromRoom();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("LobbyView.fxml"));
Parent root = (Parent) loader.load();
LobbyController lobbyController = (LobbyController)loader.getController();
lobbyController.setClientThread(client);
lobbyController.setNameAndBalance(client.getPlayer().getName());
Scene scene = new Scene(root);
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
And later in other part of programe:
if(isFinished()){
//here I want write leaving this screen and getting back to previous
}
First, find another way to get a reference to the Stage. Since you almost certainly have a reference to some node in the scene in your controller, you can replace
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
with
Stage stage = (Stage) anyNode.getScene().getWindow();
where anyNode is just something you have injected into the controller.
Now you don't need the parameter at all, so you can just remove it. I.e. you end up with
#FXML
private Node anyNode ; // probably a more specific type than Node.
#FXML
private void leaveRoomAction() {
try {
removePlayerFromRoom();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("LobbyView.fxml"));
Parent root = (Parent) loader.load();
LobbyController lobbyController = (LobbyController)loader.getController();
lobbyController.setClientThread(client);
lobbyController.setNameAndBalance(client.getPlayer().getName());
Scene scene = new Scene(root);
Stage stage = anyNode.getScene().getWindow();
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
And now you can just call the method:
if ( isFinished() ) {
leaveRoomAction()
}
I have a project in school where I have to develop a program where you first can choose whether you want to save/read to/from a SQL DB or to save/read to/from XML.
I've made a GUI where you can choose between both methods.
The GUI closes after the user clicks on one of the buttons and the MainMenu GUI opens.
Now I need to know in the MainMenuController what the user choose.
I found online a Method to call the MainMenuController inside the first controller, with FXMLLoader.getController().
try {
Stage stage = new Stage();
FXMLLoader Loader = new FXMLLoader();
Parent root = Loader.load(getClass().getResource("MainMenu.fxml"));
MainMenuController mc = Loader.getController();
mc.setSave("sql");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
catch (Exception e) {
e.printStackTrace();
}
MainMenuController
public class MainMenuController {
private String save = null;
public void setSave(String save) {
this.save=save;
}
public String getSave() {
return save;
}
}
But when i try to access a method in MainMenuController I get a NullPointerException for
mc.setSave("sql")
First ,to understand this issue ,you should make some tricks to detect where is your problem.When you do :
System.out.println(mc);
You will find the result is null.So you can not call setSave("sql") with null object,you got a null controller because your did not specify the location of your file,but you can change some lines to resolve your problem :
try {
Stage stage = new Stage();
FXMLLoader fxm = new FXMLLoader(getClass().getResource("MainMenu.fxml"));
Parent parent = (Parent) fxm.load();
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.show();
FirstController mc = fxm.getController();
System.out.println(mc);
mc.setSave("sql");
} catch (Exception e) {
e.printStackTrace();
}
You are calling the static method FXMLLoader.load(URL). Because this is a static method, it has no effect on the state of the FXMLLoader instance you created; specifically the controller field is not set.
Instead, set the location on the FXMLLoader instance, and call the instance method load():
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("MainMenu.fxml"));
// or just FXMLLoader loader = new FXMLLoader(getClass().getResource("MainMenu.fxml"));
Parent root = loader.load();
When my JavaFX application changes the screen(stage) there is a visual glitch.
Looks like the window is set on the bottom left of the screen and after that it runs to the middle.
How to avoid this glitch?
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("FXMLChamado.fxml"));
Parent root1 = (Parent) fxmlLoader.load();
// get stage
Stage stage = (Stage) new Stage();
stage.centerOnScreen();
stage.setScene(new Scene(root1));
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(
((Node)event.getSource()).getScene().getWindow() );
stage.setTitle("My App");
stage.show();
} catch (IOException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
I have Controller.java for Scene.fxml and ControllerSettings.java for WindowSettings.fxml. In Controller.java I create a new popup window (no dialog) with following method:
#FXML
public void handleSubmenuSettings(ActionEvent event) throws IOException {
Stage stage;
Parent root;
ControllerSettings controller;
stage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource("WindowSettings.fxml"));
root = (Parent) loader.load();
controller = (ControllerSettings) loader.getController();
stage.setScene(new Scene(root));
stage.setTitle("Settings");
stage.initModality(Modality.APPLICATION_MODAL);
stage.setResizable(false);
stage.initOwner(submenuSettings.getScene().getWindow());
stage.showAndWait();
stage.setOnCloseRequest(e -> {
e.consume();
controller.saveSettings();
stage.close();
});
}
I want to save the settings when closing the new popup window but that doesn't work with stage.setOnCloseRequest.
The showAndWait() method will block execution until the window has closed; i.e. subsequent statements will not be executed until after the window is closed. So you don't register the listener for the close request until after the window has been closed. Clearly, no request to close the window will occur after the window is closed, so your handler is never invoked.
It's not really clear why you are using a close request handler anyway. Presumably you simply want to call controller.saveSettings() after the window closes. Since you are using showAndWait() you can just do:
#FXML
public void handleSubmenuSettings(ActionEvent event) throws IOException {
Stage stage;
Parent root;
ControllerSettings controller;
stage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource("WindowSettings.fxml"));
root = (Parent) loader.load();
controller = (ControllerSettings) loader.getController();
stage.setScene(new Scene(root));
stage.setTitle("Settings");
stage.initModality(Modality.APPLICATION_MODAL);
stage.setResizable(false);
stage.initOwner(submenuSettings.getScene().getWindow());
stage.showAndWait();
controller.saveSettings();
}
I want to open a new scene with a controller but I get an IOException when I put the controller in it.
This is my method:
private void forgotAccount (ActionEvent event) {
try {
Node node = (Node) event.getSource();
Stage stage = (Stage) node.getScene().getWindow();
Scene scene = stage.getScene();
FXMLLoader loader = new FXMLLoader(Login.class.getResource("/mattiashellkvist/forgotAccount.fxml"));
loader.setController(new ForgotAccountController());
AnchorPane root = (AnchorPane) loader.load();
scene.setRoot(root);
stage.sizeToScene();
}
catch (IOException e) {
System.out.println("Something went wrong");
}
}
code is correct...please check your fxml location(which you provided to FXMLLoader) and fxml file for any error...and in catch use e.getMessage() to get detailed problem (i.e. System.out.println("Something went wrong "+e.getMessage());)