JavaFX FXMLLoader getController NullPointerException - javafx

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();

Related

Opening fxml file for certain time and go back to the main screen?

How do I display an fxml file for some seconds and close that fxml file and return to the mainpage.fxml?
I have tried to add hideThispage method to the initialize method in the controller class of the fxml but I guess the initialize methods just runs before the class is actually loaded so I cannot run this code.
#FXML
public void hideThisPage() throws InterruptedException, IOException {
Window window = new Stage();
PauseTransition pause = new PauseTransition(Duration.seconds(5));
pause.setOnFinished(e -> window.hide());
pause.play();
FxmlDisplay fxmlDisplay = new FxmlDisplay();
fxmlDisplay.stageSelection("View/Main.fxml");
}
To return to the main.fxml or any fxml I have a method that I call:
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(path));
Parent root = fxmlLoader.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
In my case, I have a print button in my printreceipt.fxml file that prints the contents. Then it switches to the printpage.fxml ( i am able to switch to the page) But my problem is the printpage.fxml is supposed to be displayed only for 5 seconds and close. then it should go back to main.fxml. how and where do I call the hidethisPage() method?
#FXML
void printRandomTicket(ActionEvent event) throws SQLException, ClassNotFoundException, JRException, IOException, InterruptedException {
FxmlDisplay fxmlDisplay = new FxmlDisplay();
((Node) event.getSource()).getScene().getWindow().hide();
fxmlDisplay.stageSelection("/View/Dialogs/PrintingTicket.fxml");
GenerateTicket generateTicket = new GenerateTicket();
generateTicket.generateTicket();
PrintTicket printTicket = new PrintTicket();
printTicket.printTicket();
}
I hope this clarifies it.

Switching scenes in JavaFX with ActionEvent

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()
}

Call a method of a controller from another controller JavaFX

I have a problem, i'm doing a program that simulates the FCFS algorithm. I'm working with threads. The thing is that when I press T the program needs to interrupt the thread and show a window(stage) with a table, when I close the stage i need to start again the thread, so my idea is that from the second controller call the function of the other controller and then close the stage
Here is where i call the second stage:
case T:
banderaPause=true;
th.interrupt();
Stage stTableView = new Stage();
FXMLLoader loader = new FXMLLoader();
Pane root = null;
try {
root = loader.load(getClass().getResource("showTable.fxml").openStream());
showTableController stController = (showTableController)loader.getController();
stController.init(arreglo);
stTableView.setTitle("Programa 4");
stTableView.setScene(new Scene(root, 950, 375));
stTableView.setX(2.00);
stTableView.setY(300.00);
stTableView.show();
stTableView.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
System.out.println("ya cerre");
}
});
} catch (IOException e1) {
e1.printStackTrace();
}
break;
And here is where i tried to call the method from the second controller:
case C:
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("second.fxml"));
Parent root = loader.load();
Controller n = loader.getController();
n.Continua();
Stage stage = (Stage) closeButton.getScene().getWindow();
stage.close();
} catch (IOException e1) {
e1.printStackTrace();
}
break;
But the stage just close and the method was never called
From the javadoc for onCloseRequested (emphasis mine):
Called when there is an external request to close this Window.
So the handler is not executed, if you call close yourself.
For Stages that are not the primary stage there is an option to wait for the window to be closed, however: Stage.showAndWait, so you could use this instead of registering an event handler:
stTableView.showAndWait();
// Print to console after stage is closed
System.out.println("ya cerre");

Issues with MouseControl in a different fxml using javafx

I am sorry to ask this silly question. I am unable to solve it and I need guidance.
In my application I start my main java code with menu as
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("MONC GUI :: Abhijit Bhattacharyya");
FXMLLoader loader = new FXMLLoader(MoncGUI.class.getResource("RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
//Scene scene = new Scene(rootLayout);
rootScene = new Scene(rootLayout);
primaryStage.setScene(rootScene);
RootLayoutController controller = loader.getController();
controller.setMainApp(this);
primaryStage.show();
}
......
Then I opt to go to a particular menu page by opening another fxml in the main class as
public void GeomStart() {
try {
FXMLLoader loader = new FXMLLoader(MoncGUI.class.getResource("Geom.fxml"));
AnchorPane geomPage = (AnchorPane)loader.load();
rootLayout.setCenter(geomPage);
GeomController controller = loader.getController();
controller.setMyScene(rootScene);
} catch (IOException ex) {
System.out.println(" Problem in loading geometry set");
Logger.getLogger(MoncGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
The geom.fxml is associated with geomController.java which puts a primitive geometric form on the screen and I want it to be rotated. I find mouseHandler code in the internet which should be activated as screen is passed.
I am confused which screen should I pass. Is it the root screen initiated by the main class at the start or I need to define a new screen locally here in this controller. I tried with a screen local to this controller yet the code handle is not passed to MouseHandler code.
Thanks and Regards
There is no need to pass the scene arround at all. Inside your controller you have access to the nodes which you have defined in your FXML file. Once this file is loaded and you have attached its root node to the scene graph you can get the scene by calling the .getScene() method of any of these nodes.

[A]How to use setFullScreen methode in javafx?

I have a stage with these properties
stage = new Stage(StageStyle.DECORATED);
stage.setFullScreen(true);
stage.setFullScreenExitHint("");
stage.setTitle("My App");
stage.getIcons().add(new Image(icon-address));
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("start.fxml"));
fxmlLoader.setController(this);
...
...//and other properties
It is in full screen in this stage. I have a button and each time I click on it , a method of another class is called and the reference of this stage is passed to it.
For example, if I have two classes Start and ButtonClicked
In Start, I have this :
Button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
buttonClicked a = new buttonClicked ();
try {
a.render(stage);
} catch (Exception ex) {
Logger.getLogger(menuController.class.getName())
.log(Level.SEVERE, null , ex);
}
}
});
Now, the render method is called and I have the following code inside render :
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("buttonclicked.fxml"));
fxmlLoader.setController(this);//set Controller for our fxml file
loader = fxmlLoader.load();//loader is a stackPane because buttonclick.fxml has stackPane
stage.setScene(new Scene(loader));
stage.setFullScreen(true);
...
The problem is, if user clicks on button, stage become a 1024x700(because i have pictures in start.fxml and buttonclicked.fxml. The size of both the picture is 1024x700
After a moment, it becomes full screen. How can i fix this ?
I want to kill the delay in full screen
Thanks
Try
stage.getScene().setRoot(loader);
in render method.
By doing this, the creation of a new scene is eliminated. Therefore I guess, some UI related updates and calculations that must be done after the scene has been shown, are also eliminated.

Resources