How to reference primaryStage [duplicate]

2020-02-06 05:09发布

问题:

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.

回答1:

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.



回答2:

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


回答3:

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;
      }

     }