【问题标题】:Why when I create a tab with scenebuilder it says not a node?为什么当我使用场景构建器创建选项卡时它说不是节点?
【发布时间】:2016-08-24 09:10:14
【问题描述】:
@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();
    }
}

它确实适用于我的 tabpane 的 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.

如何使这些选项卡实际上成为一个节点?有没有特定的方法来创建它们?

【问题讨论】:

  • 您好,Kiper,请在您的问题文本中使用正确的大小写,这样更容易阅读,您可能会获得更多的支持和答案。我已经修好了这个。最好的问候。
  • 似乎fooTabPage.fxml 包含一个Tab 作为根节点。这应该是 Tab 的内容。当然你也可以使用Tab作为fooTabPage.fxml的根元素,但是你需要删除周围的&lt;Tab&gt;&lt;content&gt;&lt;/content&gt;&lt;/Tab&gt;部分,这样fxml变得更难重用了。

标签: javafx


【解决方案1】:

Tab 不是Node 的子类,从JavaDocs 可以看出。这样做的原因是 JavaFX 的作者希望标签放置在 TabPanes 中:如果 TabNode 的子类,那么您可以这样做,例如,@987654328 @,这没有任何意义(我怀疑 JavaFX 的作者不想对 Tab 进行防御性编码来处理这些场景。所以 TabObject 的子类,TabPane 有一个ObservableList&lt;Tab&gt; 可以通过getTabs() 访问。

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

所以如果你有如下 FXML 代码:

<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")));

由于 setContent 应为 Node,因此只有在 fooTabPage.fxml 的根元素引用 Node 时才会成功。

相反,如果fooTabPage.fxml 的根元素是Tab,那么您需要&lt;fx:include&gt; 出现在预期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 实例可能更有用,例如

<?xml version="1.0" encoding="UTF-8"?>
<!-- imports .... -->
<BorderPane fx:controller="..." xmlns:fx="http://javafx.com/fxml/1">
    <!-- define content here... -->
</BorderPane>

然后做(在你提供的链接中):

<TabPane>
    <tabs>
        <Tab title="...">
            <content>
                <fx:include source="fooTabPane.fxml" />
            </content>
        </Tab>
    </tabs>
</TabPane>

【讨论】:

    猜你喜欢
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-05
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多