Выбор JavaFX TabPane не будет работать должным образом

У меня есть две *.fxml формы с контроллерами. Первый - Окно, второй - ProductPane.

Упрощенный Window.fxml это:

<BorderPane prefWidth="650.0" prefHeight="450.0" fx:controller="package.WindowController">
    <center>
        <TabPane fx:id="tabsPane">
            <tabs>
                <Tab fx:id="productsTab" text="Products"/>
                <Tab fx:id="warehouseTab" text="Warehouse"/>
                <Tab fx:id="saleTab" text="Sale"/>
            </tabs>
        </TabPane>
    </center>
</BorderPane>

Контроллер для Window.fxml:

public class WindowController {
    @FXML
    private TabPane tabsPane;

    @FXML
    private Tab productsTab;

    @FXML
    void initialize() {
        sout("Main Window initialization...");

        tabsPane.getSelectionModel().selectedIndexProperty().addListener((e, o, n) -> {
            sout("Changed to " + n);
        });

        tabsPane.getSelectionModel().selectedItemProperty().addListener((e, o, n) -> {
            sout("New item: " + n);
            // Load ProductPane content:
            if(n == productsTab) {
                try {

                    Parent p = FXMLLoader.load(getClass().getResource("productPane.fxml"));
                    n.setContent(p);

                } catch(IOException ex) {
                    ex.printStackTrace();
                }
            }
        });

        sout("Select first item...");
        tabsPane.getSelectionModel().selectFirst();

        // This methods also don't work
        // tabsPane.getSelectionModel().clearAndSelect();
        // tabsPane.getSelectionModel().select(productTab);
        // tabsPane.getSelectionModel().select(0);
    }
}

Проблема в том, что когда я загружаю Window.fxml в main() и запускаю его, появляется окно с пустой первой вкладкой.

Отладочный вывод:

Main Window initialization...
Select first item...

Но ProductPane не загружен и слушатель не вызывает. Если я переключаюсь между вкладками в Window, слушатели срабатывают и вкладка Products загружается правильно.

В чем проблема?

1 ответ

Решение

Вы добавили ChangeListener к модели выбора панели вкладок, которая, конечно, получает уведомление при изменении выбора. По умолчанию выбрана первая вкладка, поэтому во время добавления прослушивателя изменений первая вкладка уже выбрана. Это значит, когда вы звоните selectFirst()выбор не меняется (потому что вы просите выбрать уже выбранную вкладку), поэтому слушатель не уведомляется.

Решение немного уродливое: вам просто нужно напрямую загрузить содержимое вкладки продуктов, если вкладка продуктов выбрана во время добавления прослушивателя. Я бы выделил этот код в отдельный метод, чтобы избежать слишком большого количества повторений:

@FXML
void initialize() {
    System.out.println("Main Window initialization...");

    tabsPane.getSelectionModel().selectedIndexProperty().addListener((e, o, n) -> {
        System.out.println("Changed to " + n);
    });

    tabsPane.getSelectionModel().selectedItemProperty().addListener((e, o, n) -> {
        System.out.println("New item: " + n);
        // Load ProductPane content:
        if(n == productsTab) {
            loadProductsTab();
        }
    });

    if (tabPane.getSelectionModel().getSelectedItem() == productsTab) {
        loadProductsTab();
    }
}

private void loadProductsTab() {
    try {

        Parent p = FXMLLoader.load(getClass().getResource("productPane.fxml"));
        productsTab.setContent(p);

    } catch(IOException ex) {
        ex.printStackTrace();
    }
}

Если вы обнаружите, что вам очень нужны такие функции, вас может заинтересовать инфраструктура ReactFX, которая (я думаю) имеет встроенную функциональность, которая обрабатывает подобные случаи.

Другие вопросы по тегам