【问题标题】:JavaFx : tab item does not fill the contentJavaFx:选项卡项未填充内容
【发布时间】:2022-11-23 23:44:13
【问题描述】:

我有一个 TabPane 声明如下:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TabPane?>

<TabPane fx:id="rootNode" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="@dark_theme.css" tabClosingPolicy="UNAVAILABLE" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.AppController" />

我想从我的控制器添加标签。所以我这样做:

    jsonConfig.getAvailableChannelIds().forEach( chId -> {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("tab_item.fxml"));
            Tab item = fxmlLoader.load();
            item.setText(String.format("%d", chId));
            rootNode.getTabs().add(item);
        }catch (Exception e) {
            e.printStackTrace();
        }
    });

“tab_item.fxml”看起来如下:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Tab?>

<?import javafx.scene.layout.VBox?>
<Tab xmlns:fx="http://www.w3.org/1999/XSL/Transform">
   <VBox>
         <fx:include source="test.fxml"/>
   </VBox>
</Tab>

最后是“test.fxml”:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: red;" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" />

这就是我所拥有的:

我缺少什么来用红色方块填充 Tab 内容?

【问题讨论】:

  • 我的猜测是test.fxml中的AnchorPane需要maxHeightmaxWidth设置为Infinity
  • 您将首选尺寸明确设置为 600x400。你希望发生什么/
  • 不相关:此 xmlns:fx="http://www.w3.org/1999/XSL/Transform" 不是 FXML 的名称空间。您提供的 XML 命名空间用于 XSL transforms,这根本不是您的文档所使用的。而是使用xmlns:fx="http://javafx.com/fxml"。在这种情况下,命名空间只对 XML 验证(您没有使用)和帮助工具(如 IDE)提供更好的编辑帮助很重要。
  • 如果你也摆脱了最小和最大尺寸,那么允许锚窗格增长,然后你可以告诉VBox使test.fxml中的锚窗格增长到它喜欢的大小,使用通常的@ 987654340@设置。不过,我真的不明白为什么你在那里有 VBox

标签: javafx tabs


【解决方案1】:

大多数布局窗格,例如VBox,默认情况下会尝试将其内容调整为首选大小,并会尽一切努力将大小保持在指定为最小和最大的约束范围内。

我推荐阅读旧的 Oracle layout tutorial。它是很久以前(Java 8 之前)编写的,所以代码风格有点过时,但布局概念仍然相关。另请阅读 layout package 的 Javadocs,并且大概您已经阅读了您正在使用的任何布局组件的 Javadocs(如果没有,您应该始终阅读您使用的类的文档)。

你有

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" 
            minHeight="-Infinity" minWidth="-Infinity" 
            prefHeight="400.0" prefWidth="600.0" 
            style="-fx-background-color: red;"
            xmlns="http://javafx.com/javafx/19" 
            xmlns:fx="http://javafx.com/fxml/1" />

它明确地将首选大小设置为 600x400 像素,并将最小和最大大小设置为 -Infinity,这是标记值 Region.USE_PREF_SIZE。因此,VBox 将始终将内容调整为 600x400 像素(只要 VBox 中有足够的空间即可)。

删除所有这些设置(我也更正了名称空间,尽管您在这里并不真正需要它):

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>

<AnchorPane style="-fx-background-color: red;"
            xmlns:fx="http://javafx.com/fxml" />

现在 VBox 仍会尝试将内容设置为其首选大小,默认情况下,该大小是根据其自己的内容计算得出的。由于锚窗格为空,因此首选大小将计算为 0x0。但是,由于现在最大尺寸不受限制,您可以告诉 VBox 让它增长:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Tab?>

<?import javafx.scene.layout.VBox?>
<Tab xmlns:fx="http://javafx.com/fxml/">
        <VBox fillWidth="true">
        <fx:include source="test.fxml" VBox.vgrow="ALWAYS" />
        </VBox>
</Tab>

现在test.fxml中定义的内容将填充VBoxTab 的行为是让它的内容填充选项卡的整个区域,因此 VBox 将填充选项卡。

当然,一开始为什么要将 test.fxml 包装在 VBox 中并不是很清楚。由于默认情况下选项卡将由其内容填充,为什么不简化为

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Tab?>

<Tab xmlns:fx="http://javafx.com/fxml/">
        <fx:include source="test.fxml" />
</Tab>

这是一个完整的示例,删除了所有不必要的硬编码大小和冗余布局窗格:

HelloApplication.java:

package org.jamesd.examples.tab;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 320, 240);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

hello-view.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TabPane?>

<TabPane fx:id="rootNode"
         tabClosingPolicy="UNAVAILABLE"
         xmlns:fx="http://javafx.com/fxml/"
         fx:controller="org.jamesd.examples.tab.AppController" />

AppController.java:

package org.jamesd.examples.tab;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;

public class AppController {

    @FXML
    private TabPane rootNode ;

    public void initialize() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("tab_item.fxml"));
            Tab item = fxmlLoader.load();
            item.setText(String.format("%d", 42));
            rootNode.getTabs().add(item);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

tab-item.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Tab?>

<Tab xmlns:fx="http://javafx.com/fxml/">
        <fx:include source="test.fxml" />
</Tab>

test.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>

<AnchorPane style="-fx-background-color: red;"/>

【讨论】:

    【解决方案2】:

    好的,所以我在这里至少找到了一个解决方法 -> 只需将 fx:include 与 AnchorsPane 包装起来就可以了:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Tab?>
    
    <?import javafx.scene.layout.AnchorPane?>
    <Tab xmlns:fx="http://www.w3.org/1999/XSL/Transform">
       <content>
           <AnchorPane>
                <fx:include source="test.fxml" AnchorPane.topAnchor="0" AnchorPane.rightAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.bottomAnchor="0"/>
           </AnchorPane>
       </content>
    </Tab>
     
    

    【讨论】:

    • 您将 pref 大小明确设置为您不想要的东西的解决方案是找到一个强制忽略 pref 大小的解决方法????
    • @James_D 除了在你的评论中有点傲慢之外,你的建议是什么?如果我在某个地方错了,请尽可能直接指定它吗?
    • 不要明确设置首选大小。
    • @James_D 如我所见,这还不够,如果我继续使用 VBox,我根本看不到任何渲染。所以这里的重点是使用AnchorPane作为Tab项的内容
    • 您还将最大大小明确设置为 USE_PREF_SIZE (-Infinity)。摆脱所有这些,您可以以自然的方式使用布局设置。为什么无论如何都需要将选项卡的内容包装在窗格中?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    相关资源
    最近更新 更多