0

I am trying to make it such that I can create a new tab for my TabPane from within another tab but I am having some difficulty. Currently I have the TabPane set up in the "main-window.fxml" with the corresponding MainWindowController. I have a tab within this TabPane which, via fx:include, displays "mainTab.fxml" to the scene graph, controlled by MainTabController. Now from within the "mainTab" I want a button to be able to add an additional tab to the TabPane, but since this is requires a reference to the TabPane in "main-window", I have created a static method in "main-window". When the run the code below I get a NullPointerException on this line in the MainWindowController:

mainTabPane.getTabs().add(new Tab(team.getTeamName()));

Could someone please tell me as to why it is giving this exception and how I can begin to work around it?

main-window.fxml:

<TabPane fx:id="mainTabPane">
    <tabs>
        <Tab fx:id="mainTab" text="Main" closable="false">
            <fx:include source="mainTab.fxml" fx:id="mainWindowTab" alignment="CENTER"/>
        </Tab>                
    </tabs>
</TabPane>

mainTab.fxml (the event handler for the button):

@FXML
public void handleSubmit() {
    String teamName = teamNameTextField.getText();
    Roster roster = rosterComboBox.getValue();
    int startWeek = spinner.getValue();
    Team newTeam = new Team(teamName, startWeek, roster);
    TeamData.addTeam(newTeam);
    MainWindowController controller = new MainWindowController();
    controller.createTeamTab(newTeam);

}

MainWindowController:

public class MainWindowController {

    @FXML
    private TabPane mainTabPane;

    public void createTeamTab(Team team) {
        mainTabPane.getTabs().add(new Tab(team.getTeamName()));

    }
}
James_D
  • 201,275
  • 16
  • 291
  • 322
George
  • 3
  • 3
  • "since this is requires a reference to the TabPane in "main-window", I have created a static method": this doesn't really make sense. You've identified the problem: you don't have a reference to the tab pane in the controller for the main tab. The solution is not to make anything static: the solution is to provide a reference to the `MainWindowController` instance to the `MainTabController`. – James_D May 22 '17 at 11:56
  • Thanks for the response. Instead of making anything static then I can provide an instance of the `MainWindowController` to the `MainTabController` and run the method from there but I still get the same error. Sorry if I am missing something obvious here but I'm still very new to programming! – George May 22 '17 at 13:52
  • [Edit] your question to show that version. (Note: you have to provide the actual controller to `MainTabController`, not just *any* instance of `MainWindowController`.) – James_D May 22 '17 at 13:53
  • I created an instance of `MainWindowController` which would be why it still isn't working. What do you mean when you say "provide the actual controller to `MainTabController`"? Thanks – George May 22 '17 at 15:13
  • In the `MainWindowController`'s `initialize()` method you would do something like `mainWindowTabController.setWindowController(this);`, with the obvious methods and fields defined. – James_D May 22 '17 at 15:15
  • Hi James, forgive me if I am being dumb but what are the obvious methods and fields? I'm still struggling to understand how I can reference the TabPane from `MainWindow` in the `handleSubmit` method in the `MainTabController` – George May 22 '17 at 17:22
  • You would need a `mainWindowTabController` field in `MainWindowController` and a `setWindowController` method in `MainTabController` (or whatever the controller class is for `mainTab.fxml`).... Again, if you [edit] your question to show the attempt where you don't make anything static, it would be easier to help you. – James_D May 22 '17 at 17:58
  • I've updated the question to creating an instance of MainWindowController which is still wrong. Sorry I should have been more specific before, what would the setWindowController method entail? – George May 22 '17 at 19:08

1 Answers1

1

Your code doesn't work because you are not calling createTeamTab(...) on the controller: you are calling it on another instance of MainWindowController that you created. (The fields annotated @FXML are initialized in the controller instance by the FXMLLoader when the FXML is loaded: for fairly obvious reasons they will not be set to the same values in arbitrary other instances of the same class.) You need to get a reference to the controller you are using for the main tab, and pass it a reference to the main controller.

You didn't tell us the class name for the controller of mainTab.fxml: I will assume it is MainTabController (so just change it to whatever class name you actually use).

In MainWindowController, do:

public class MainWindowController {

    @FXML
    private TabPane mainTabPane;

    @FXML
    // fx:id of the fx:include with "Controller" appended
    private MainTabController mainWindowTabController ; 

    public void initialize() {
        mainWindowTabController.setMainWindowController(this);
    }

    public void createTeamTab(Team team) {
        mainTabPane.getTabs().add(new Tab(team.getTeamName()));

    }
}

and then in MainTabController do

public class MainWindowController {

    private MainWindowController mainWindowController ;

    public void setMainWindowController(MainWindowController mainWindowController) {
        this.mainWindowController = mainWindowController ;
    }

    @FXML
    public void handleSubmit() {
        String teamName = teamNameTextField.getText();
        Roster roster = rosterComboBox.getValue();
        int startWeek = spinner.getValue();
        Team newTeam = new Team(teamName, startWeek, roster);
        TeamData.addTeam(newTeam);
        mainWindowController.createTeamTab(newTeam);

    }

}
James_D
  • 201,275
  • 16
  • 291
  • 322
  • ahh yes this is exactly the solution I was looking for thank you! I don't think I fully understood how the controllers worked and that I had to reference THE instance rather than any old instance, but this clears that up! Much appreciated – George May 23 '17 at 18:01