5

There is an possibility to get Controller instance from Node ?? for example AnchorPane on Tab ?

I have some AnchorPanes where I load different Controllers and I would like to verify which controller is already loaded

VANILKA
  • 634
  • 1
  • 13
  • 32
  • May be this is helpful to you. [passing-parameters-javafx-fxml](http://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml/40193164#40193164) – CTN Nov 23 '16 at 06:08

2 Answers2

11

Nodes do not contain any information about a controller used with the fxml file used to create it by default, since fxml is just one way of creating a scene. However you could attach information like this to the userData/properties in the fxml:

<AnchorPane xmlns:fx="http://javafx.com/fxml/1" fx:id="AnchorPane" prefHeight="400.0" prefWidth="600.0" onMouseClicked="#click" fx:controller="fxml.FXMLController">
    <!-- store controller as userData property -->
    <userData>
        <fx:reference source="controller" />
    </userData>
    <properties>
        <!-- store controller at key "foo" in properties map -->
        <foo><fx:reference source="controller" /></foo> 
    </properties>
</AnchorPane>

If you do this, you can lookup the controller at closest ancestor of a node where you added this kind of information using

public static Object getController(Node node) {
    Object controller = null;
    do {
        controller = node.getProperties().get("foo");
        node = node.getParent();
    } while (controller == null && node != null);
    return controller;
}

to retrieve the info from the properties map or using

public static Object getController(Node node) {
    Object controller = null;
    do {
        controller = node.getUserData();
        node = node.getParent();
    } while (controller == null && node != null);
    return controller;
}

to retrieve the info from the userData property.

You should probably use just one way of adding the info though, not both. Also it would be better to replace foo as key...

fabian
  • 80,457
  • 12
  • 86
  • 114
  • 1
    Digging up this question... First thanks because it solved my problem, second it appears that using this type of markup breaks the scene builder :( The problem seems to be with using subelements under properties. Using attributes like abc="123" doesn't break the scene builder, but you can't use fx:reference with this method. So if I want to use the scene builder I need to comment out the controller property, edit the scene, and uncomment it when I'm done. Not ideal. – Olivier Gérardin May 25 '20 at 21:08
0

It's an old question, but if you have a main window, where you include other fxml files like this:

<AnchorPane prefHeight="900.0" prefWidth="1600.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1"
      fx:controller="MainController">
<!--  <HBox></HBox>, some elements here, your normal usual FXML-->
  <fx:include fx:id="someAnchorPane" source="SomeAnchorPane.fxml"/>
</AnchorPane>

and your SomeAnchorPane.fxml has fx:controller property set to SomeOtherController, then you can add a controller field in your MainController like this:

@FXML private SomeOtherController someAnchorPaneController;

And it will inject appropriate controller in this field automatically.

The key thing here is that your field has to be named "fx:id+Controller" for it to work.

graynk
  • 131
  • 1
  • 2
  • 17