JavaFX TabPane选择无法正常工作

时间:2015-05-16 10:28:35

标签: javafx controller selectionmodel

我有两个带控制器的* .fxml表单。首先是Window,第二个 - ProductPane。

Simplified 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);
    }
}

问题是:当我在main()中加载Window.fxml并启动它时,窗口显示为空的第一个选项卡。

调试输出:

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

但是ProductPane没有加载,监听器也没有调用。如果我在Window中的选项卡之间切换,则会触发侦听器并正确加载“产品”选项卡。

有什么问题?

1 个答案:

答案 0 :(得分: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框架感兴趣,我认为该框架具有处理这些案例的内置功能。<​​/ p>