3

I'll try to get in JavaFX 2 and used a simple demo app. The Project consists of 3 Files, the Main.java, the Controller.java and the sample.fxml.

In Sample.fxml i declared the controller:

<GridPane fx:controller="sample.Controller"
      xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
</GridPane>

And in my Main.java I try to access the controller

    FXMLLoader loader = new FXMLLoader();
    Parent root = loader.load(getClass().getResource("sample.fxml"));
    System.out.println(loader.getController()); //prints always null

So my first idea was that the mapping doesn't work. So I added a initialize method in the controller.

@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
    System.out.println("init");
}

The output is now:

init

null

So my Question now is how can i access the controller of a given fxml file?

Community
  • 1
  • 1
reikla
  • 33
  • 1
  • 4

2 Answers2

4

The FXMLLoader.load(URL) method is a static method. So when you execute

  FXMLLoader loader = new FXMLLoader();
  Parent root = loader.load(getClass().getResource("sample.fxml"));

you are not loading the FXML file from the instance of the FXMLLoader that you constructed ("loader"). (You're actually invoking the static method through an object reference.) Hence the loader's controller never gets initialized.

You need

  FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
  Parent root = loader.load();

This constructs a loader with a location specified, and then the load() method, which is not a static method, is properly invoked on the FXMLLoader instance. Then

System.out.println(loader.getController());

will give the correct result.

James_D
  • 201,275
  • 16
  • 291
  • 322
  • Thanks! Hope the loader gets improved in the releases to come. – Houston Feb 05 '17 at 14:41
  • @Houston What improvement do you think it needs? – James_D Feb 05 '17 at 14:43
  • @James_D Looks like many ppl don't immediately realize that load is a static method hence causing confusion. The api should avoid this confusion? Just a thought... All is well now though. – Houston Feb 07 '17 at 19:09
2

In addition to James_D's answer, I recommend to use the fx:root construct. Then you can inject the custom control (implemented by a controller) in another controller using the @FXML annotation.

Puce
  • 37,247
  • 13
  • 80
  • 152
  • Please can you explain the fx:root construct? – reikla Apr 07 '14 at 11:32
  • @reikla a simple search for "fx:root tutorial" will get you a couple of links, e.g. http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm If you have a specific question, please come back and ask a new question. – Puce Apr 07 '14 at 11:35
  • "the controller property of FXMLLoader doesn't get set when loading an FXML file" is completely incorrect. As long as you invoke the load() method on the FXMLLoader instance, it will be set. – James_D Apr 07 '14 at 11:36
  • Thanks! Thats another way i think. But I prefere James_D's solution! – reikla Apr 07 '14 at 11:43