18

I use .fxml-Files for the view-layer of my application. Each fxml has a controller attached to it

<AnchorPane fx:controller="movielistjavafx.view.MainWindowController">

Let's assume I have a mainFrame and it's controller. The mainFrame.fxml is loaded in the start(Stage)-method.

Now you would like to show a fileChooser which is attached to a Stage/Window/Whatever.

For that it would be good to let the fxml-controller know about the for example primaryStage.

Is there any way to inject it to the controller, or does the FXML know at runtime to which scene and stage it belongs?

Only idea I have is to store primaryStage in some static context, but that seems not like a way to do it to me.

Gundon
  • 2,081
  • 6
  • 28
  • 46
  • This question is 2 years older then the referenced one AND already answered. How is this a duplicate of the other one now @fabian? – Gundon Oct 18 '16 at 11:02
  • Obviously both question ask about the same problem; One of them is a duplicate. I simply chose the question with the smaller score as the dupe. BTW: That a question has been answered does not indicate it's not a dupe. It just means there were not enough close votes before it was answered. If you do not agree with this decision, you could still flag it for moderator attention and/or bring it up on [meta]. – fabian Oct 18 '16 at 11:32

3 Answers3

35

Not FXML but the nodes (controls) in FXML (or in its Controller) know to which scene and stage they belong at runtime (after being added to the scene).
In controller class,

...
@FXML private Label label;
...
// in some method block
Stage stageTheLabelBelongs = (Stage) label.getScene().getWindow();

Alternatively you can use CDI events to get the primary stage. Look the blog entry FXML & JavaFX powered by CDI & JBoss Weld.

dave_k_smith
  • 655
  • 1
  • 7
  • 22
Uluk Biy
  • 48,655
  • 13
  • 146
  • 153
  • 4
    However if you this method block is `initialize(URL location, ResourceBundle resources)` after you have implemented `Initializable` then code above will give you NullPointerException. – Tomasz Mularczyk Mar 24 '15 at 13:02
8

Robust solution (can be used as a snippet): Take an event and then get control that fired that event. Use that control to get the Stage:

@FXML
private void browseDirectory(ActionEvent event) {
    Stage stage = Stage.class.cast(Control.class.cast(event.getSource()).getScene().getWindow());
    DirectoryChooser directoryChooser = new DirectoryChooser();
    File selectedDirectory = directoryChooser.showDialog(stage);
    System.out.println(selectedDirectory.getAbsolutePath());
}
zoran
  • 943
  • 11
  • 22
4

http://code.makery.ch/java/javafx-2-tutorial-part5

Here is a good tutorial for doing that with a sample code example

       Controller...

      //Application class type variable
      public MainApp mainApp;
      public Stage stage;
       .........
       .........

     /**
      * Is called by the main application to give a reference back to itself.
      * 
      * @param mainApp
      */
       public void setMainApp(MainApp mainApp) {
       this.mainApp = mainApp;


       }
       }

       .....

       .........
       @FXML
       public void initialize(){

       stage=mainApp.getStage();



      }


      Application class....

      class MainApp extends Application{

      Stage stage;
       ...
          ...

      @Override
      public void start(Stage stage) {
      this.stage=stage;
      FXMLLoader loader = new  
      FXMLLoader(MainApp.class.getResource("view/PersonOverview.fxml"));
      PersonOverviewController controller = loader.getController();

      controller.setMainApp(this);
     }

        ...
            ,,

      public getStage()
     {

      return this.stage;
      }

     }
Marco Jakob
  • 1,068
  • 1
  • 13
  • 20
Shashank
  • 41
  • 3
  • Can you please explain instead of giving one line answers. Thank you. – Freakyuser Mar 08 '13 at 11:40
  • 3
    I don't believe this answers the question. I doesn't fit my use-case at least. We tend to want to keep FXML controllers decoupled from the main app. The method from: Uluk Biy, is more appropriate for those cases. – will Dec 03 '14 at 23:10
  • 1
    why not just make static reference to primary stage in `start` method of application class? so later you can just use `MainClass.primaryStage;` ? – Tomasz Mularczyk Mar 24 '15 at 13:18
  • Tomek. +1 for simplicity! Thanks for reminding me the power of the static modifier. – rafaelbattesti Oct 02 '15 at 02:27