How to access a JavaFx Stage from a Controller?
Solution 1
In your situation, it is probably easiest to get the scene from the ActionEvent
parameter of your handler:
@FXML
private void handleSourceBrowse(ActionEvent ae) {
Node source = (Node) ae.getSource();
Window theStage = source.getScene().getWindow();
sourceDirectoryChooser.showDialog(theStage);
}
See JavaFX: How to get stage from controller during initialization? for some more information. I am not in favor of the highest rated answer though, since it adds a compile time dependency to the controller after the .fxml
file has been loaded (after all that question was tagged with javafx-2
, so not sure if the above approach already worked there, and also the context of the question looks a bit different).
See also How do I open the JavaFX FileChooser from a controller class?
Solution 2
Another way is define a static getter for the Stage and Access it
Main Class
public class Main extends Application {
private static Stage primaryStage; // **Declare static Stage**
private void setPrimaryStage(Stage stage) {
Main.primaryStage = stage;
}
static public Stage getPrimaryStage() {
return Main.primaryStage;
}
@Override
public void start(Stage primaryStage) throws Exception{
setPrimaryStage(primaryStage); // **Set the Stage**
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
}
Now you Can access this stage by calling
Main.getPrimaryStage()
In Controller Class
public class Controller {
public void onMouseClickAction(ActionEvent e) {
Stage s = Main.getPrimaryStage();
s.close();
}
}
Comments
-
Sargon1 almost 2 years
I'm converting a pure JavaFx app, in which the code below worked fine when put all in one class, to a FXML one, where the Stage declaration and the button handler are in separate classes. In the a Controller, I'm trying to implement a method that will allow the user to choose a directory and store it in a variable for later use:
private File sourceFile; DirectoryChooser sourceDirectoryChooser; @FXML private void handleSourceBrowse() { sourceDirectoryChooser.setTitle("Choose the source folder"); sourceFile = sourceDirectoryChooser.showDialog(theStage); }
However, "theStage", a Stage which the method requires, only exists(if that's the right terminology) in FolderSyncer4.java:
public class FolderSyncer4 extends Application { final String FOLDER_SYNCER = "FolderSyncer"; Stage theStage; @Override public void start(Stage primaryStage) throws Exception { theStage = primaryStage; //TODO do the FXML stuff, hope this works Parent root = FXMLLoader.load(getClass().getResource("FolderSyncerMainWindow.fxml")); theStage.setScene(new Scene(root, 685, 550)); theStage.setTitle(FOLDER_SYNCER); theStage.show(); } }
How to I get around this? I need to have that method implemented again somehow, but suddenly I can't pass the stage as an argument.
-
Sargon1 over 8 yearsI thank you for your answer, but this implementation gives a java.lang.reflect.InvocationTargetException when the button is pressed.
-
Andreas Fester over 8 yearsThats strange - I tested it with a simple example, see github.com/afester/CodeSamples/tree/master/Java/JavaFXSample/…. Can you paste the stack trace from the exception to pastebin.com or something similar and add the link to it as a comment?
-
Sargon1 over 8 yearsHere it is. Thanks for the help, I'm not too good at deciphering those things. pastebin.com/3AycwLge
-
Andreas Fester over 8 yearsOk, so the root cause is a
NullPointerException
in line 75 of your controller class - what is the contents of that line? -
Andreas Fester over 8 yearsSo, according to your code in the question, did you probably forget to create the
DirectoryChooser
, likeDirectoryChooser sourceDirectoryChooser = new DirectoryChooser();
? That would also explain the NPE. -
Sargon1 over 8 yearsYup, just figured it out too. It seem s to be working now, thanks.
-
Koin Arab almost 7 yearsVery nice solution but the getter and setter should be static here.