1

我有两个带有控制器的 *.fxml 表单。首先是 Window,其次是 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);
    }
}

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

调试输出:

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

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

有什么问题?

4

1 回答 1

2

You added a ChangeListenerto the tab pane's selection model, which of course gets notified when the selection changes. 默认情况下,第一个选项卡被选中,因此在添加更改侦听器时,第一个选项卡已经被选中。这意味着当您调用 时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框架感兴趣,它(我认为)具有处理这些情况的内置功能。

于 2015-05-16T14:10:45.003 回答