1

I've adjusted my controller constructor and fxml so that all setup of the fxml to the controller is in the fxml except for the FXML construction and the fxml loading. Here is my controller:

public class MainOverviewTab extends Tab {

@FXML private AnchorPane content;

public MainOverviewTab() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("main_overview_tab.fxml"));
    // fxmlLoader.setRoot(content);
    // fxmlLoader.setController(this);      

    try {
        fxmlLoader.load();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

and my fxml file:

<AnchorPane id="AnchorPane" 
    fx:id="content" 
    fx:controller="dominion.application.controller.MainOverviewTab"
    ...other settings >

        <children>
            ....
        </children>
</AnchorPane>

The stackoverflow occurs when the fxmlLoader.load() is called and goes back to FXMLLoader fxmlLoader = new FXMLLoader(...) and then fxmlLoader.load() is called again... Why is this happening and how do I keep my controller constructor the same and load the fxml the same? Or is this not possible?

j will
  • 3,747
  • 11
  • 41
  • 64
  • [this answer](http://stackoverflow.com/a/11297531/180100) might help –  Dec 11 '13 at 06:11

3 Answers3

1

You should not call FXml loader with in constructor. because when you load fxml file by using FXml loader , it will create MainOverviewTab again and again recursively. so it cause stack overflow error. If you remove the code from constructor and call from explicit method it will work.

public static void mainTabLoader() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("main_overview_tab.fxml"));
    // fxmlLoader.setRoot(content);
    // fxmlLoader.setController(this);      

    try {
        fxmlLoader.load();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

Wolfgang Fahl
  • 15,016
  • 11
  • 93
  • 186
Murali
  • 341
  • 2
  • 7
  • 24
  • The setRoot and setController calls are not needed in this case. – tomsontom Dec 11 '13 at 07:18
  • but it works when i uncomment setRoot and setController and i remove those attributes in the fxml. – j will Dec 12 '13 at 05:41
  • Without the fx:controller attribute in the FXML, the FXMLLoader's load(...) method will not instantiate the controller. So removing the attribute breaks the infinite recursion. – James_D Dec 12 '13 at 18:06
1

If you call setController(...) on your FXMLLoader instance, you should not specify the controller in the FXML file. Remove the fx:controller attribute from the FXML file and uncomment the setRoot(...) and setController(...) calls and it should work.

James_D
  • 201,275
  • 16
  • 291
  • 322
  • But the lines I commented out in the constructor is what I want to delete. I also want to leave the attributes in the FXML file, and I want all this without getting an exception. – j will Dec 12 '13 at 05:59
  • 1
    In that case, you should move the loading of the FXML out of the controller class. Typically it would be done in the start(...) method of your Application subclass, though if you are using multiple FXMLs it might be done elsewhere. The fxmlLoader.load(...) method parses the FXML file, sees the fx:controller attribute, instantiates the controller, and calls its initialize() method. If you invoke fxmlLoader.load(...) with the same FXML file in the constructor (or initialize() method), you end up with infinite recursion. – James_D Dec 12 '13 at 11:51
1

This is what happens when a controller constructor tries to load FXML with a fx:controller attribute naming it, it get infinitely recursive. Been there... Clever use of fxmlLoader.setControllerFactory(factoryObject) can get around that.

See my answer for an FXML based control retaining fx:controller attribute in root element, this can be adapted for other controller creation.

Infernoz
  • 131
  • 4