为什么当我用scenebuilder创建一个标签时,它不是一个节点?

时间:2016-08-24 09:10:15

标签: javafx

@Override
public void start(Stage primaryStage) {
    this.primaryStage = primaryStage;
    this.primaryStage.setTitle("AddressApp");

    initRootLayout();

    showTabOverview();
}

/**
 * Initializes the root layout.
 */
public void initRootLayout() {
    try {
        // Load root layout from fxml file.
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(Main.class.getResource("rootLayout.fxml"));
        rootLayout = (BorderPane) loader.load();

        // Show the scene containing the root layout.
        Scene scene = new Scene(rootLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

/**
 * Shows the Tab overview inside the root layout.
 */
public void showTabOverview() {
    try {
        // Load person overview.
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(Main.class.getResource("tabLayout.fxml"));
        TabPane TabOverview = (TabPane) loader.load();

        // Set person overview into the center of root layout.
        rootLayout.setCenter(TabOverview);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

它适用于我的tablab的FXML。

<TabPane xmlns:fx="http://www.w3.org/1999/XSL/Transform">
<tabs>
    <Tab text="Untitled Tab 1">
    </Tab>
    <Tab text="Untitled Tab 2">
    </Tab>
</tabs>
</TabPane>

但我尝试使用this link

上找到的这种方法添加每个标签FXML
<Tab text="Untitled Tab 1">
        <content>
            <fx:include fx:id="fooTabPage" source="fooTabPage.fxml"/>
        </content>
    </Tab>

当我为标签添加包含新来源的内容时,我会IllegalArgumentException: Unable to coerce javafx.scene.control.Tab@3885406e to class javafx.scene.Node.                                                         

如何让这些标签真正成为节点?是否有特定的方法来创建它们?

1 个答案:

答案 0 :(得分:3)

Tab不是Node的子类,您可以从JavaDocs看到。这样做的原因是JavaFX的作者希望标签只在<{1}}中放置 :如果TabPaneTab的子类,那么你可以做例如,Node,这不是真的有意义(我怀疑JavaFX的作者并不想在防御上编码HBox anyContainer = new HBox(new Tab(...));来处理这些场景。所以{{ 1}}是Tab的子类,TabObject,您可以使用TabPane访问。{/ p>

ObservableList<Tab>通过使用(很多很多)反射来工作。这允许它动态创建对象,其类由fxml文件确定,当然编译器从未看到过。因此,getTabs()没有对从FXML文件创建的对象类型进行编译时检查。因此,您为FXMLLoader的灵活性支付的价格是类型安全性的损失;作为程序员,您可以确保在FXML文件中定义正确的类型以用于其预期用途。

因此,如果你有如下FXML代码:

FXMLLoader

这松散地转化为

FXMLLoader

由于setContent预计为<Tab text="Untitled Tab 1"> <content> <fx:include fx:id="fooTabPage" source="fooTabPage.fxml"/> </content> </Tab> ,因此只有Tab tab = new Tab("Untitled Tab 1"); tab.setContent(FXMLLoader.load(getClass().getResource("fooTabPage.fxml"))); 的根元素引用Node时才会成功。

相反,如果fooTabPage.fxml的根元素是Node,那么您需要fooTabPage.fxml出现在预期Tab的地方。所以你可以<fx:include>作为

Tab

然后再做

fooTabPage.fxml

但是,如果您不假设其层次结构将放置在选项卡窗格中,则您的<?xml version="1.0" encoding="UTF-8"?> <!-- imports .... --> <Tab fx:controller="..." xmlns:fx="http://javafx.com/fxml/1"> <content> <!-- define content here... --> </content> </Tab> 文件可能会更具可重用性(尽管此级别的设计非常适合您)。因此,将<TabPane> <tabs> <fx:include source="fooTabPane.fxml" /> </tabs> </TabPane> fooTabPage.fxml实例的根元素设置为更有用,例如

fooTabPage.fxml

并做(如您提供的链接):

Node