Search code examples
javafxtabsjavafx-8fxml

JavaFx TabPane One view for each tab but different data


I'm new to the TabPanes, didn't really worked with them until now, and I need a TabPane with many Tabs but the same view(same look) for each Tab, what changes it is just the data in the tabs.

I have read JavaFX TabPane - One controller for each tab but this is not what I want, to assign a controller foreach tab. I want to do not duplicate my code, so I wold need to initialize the .fxml which contains my view only once and reuse it every time I swich between the tabs and load the appropriate data to it.

How can I achieve it?

My solution was:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.Tab?>
<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="tabpane.Controller">
    <TabPane>
        <Tab>
            <fx:include source="CommonUI.fxml" fx:id="first"/>
        </Tab>
        <Tab>
            <fx:include source="CommonUI.fxml" fx:id="second"/>
        </Tab>
        <Tab>
            <fx:include source="CommonUI.fxml" fx:id="third"/>
        </Tab>
        <Tab>
            <fx:include source="CommonUI.fxml" fx:id="forth"/>
        </Tab>
        <Tab>
            <fx:include source="CommonUI.fxml" fx:id="fifth"/>
        </Tab>
    </TabPane>
</AnchorPane>


public class Controller implements Initializable {

    MyService setrvice = MyServiceProvider.getService(MyService.class);

    @FXML
    private CommonUIController firstController;
    @FXML
    private CommonUIController secondController;
    @FXML
    private CommonUIController thirdController;
    @FXML
    private CommonUIController forthController;
    @FXML
    private CommonUIController fifthController;



    @Override
    public void initialize(URL location, ResourceBundle resources) {
      // some code.
    }

    private void load() {
        firstController.load(service.firstData());
        secondController.load(service.secondData());
        thirdController.load(service.thirdData());
        forthController.load(service.forthData());
        fifthController.load(service.fifthData());
    }
}

Solution

  • Create instance of your controller and get view component. Then replace view and update data on tab change.

    //pseudoCode
    Node controllerView  = controller.getView();
    
    TabPane tabPane = new TabPane();
    tabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, tab) -> {
        if(oldTab != null) {
            oldTab.setContent(null);
        }
        if(tab != null) {
            tab.setContent(controllerView);
            //pseudoCode
            controller.updateData();
        }
    });