如何一致地规定嵌套 JavaFX 控件的大小?

问题描述 投票:0回答:1

我正在努力发展我的编程技能,并正在 JavaFX 中构建 UI 应用程序,因为 Java 是我最擅长的语言。

不幸的是,我发现使用 FXML 构建 UI 充其量是乏味的。我决定将窗口设置为固定大小,认为第一次构建非响应式 UI 会更容易。

添加元素很容易,但事实证明要调整它们的大小是非常困难的,特别是当布局嵌套时(即 HBox 中的 TiledPane)。我认为我误解了孩子如何从父母那里继承属性,反之亦然。

在我的应用程序中,我经常嵌套,因为提供给视图的数据可能需要几秒钟的时间来加载,而且我不想频繁加载屏幕给用户带来负担。

例如,这是屏幕的 FXML,它根据您按下的按钮显示数据。我的窗口是 1600x900。我希望第二个 HBox 中的元素填充屏幕的其余部分,但我似乎没有任何调整会导致它们增长。我还想调整其他元素的大小,但我认为一旦我理解了我缺少的原则,这会更容易。

<VBox fx:id="detachmentView" visible="false">
                <HBox alignment="CENTER">
                    <Button fx:id="detachmentRules" text="Rules" styleClass="medium_button" onAction="#detachmentRulesButton"/>
                    <Button fx:id="detachmentStratagems" text="Stratagems" styleClass="medium_button" onAction="#detachmentStratagemButton"/>
                    <Button fx:id="detachmentEnhancements" text="Enhancements" styleClass="medium_button" onAction="#detachmentEnhancementButton"/>
                </HBox>
                <Separator/>
                <HBox>
                    <HBox maxWidth="666">
                        <VBox>
                            <Label text="Detachment Name:" styleClass="detachment_header"/>
                            <ListView fx:id="detachmentList" onMouseClicked="#detachmentListSelect" styleClass="detachment_list" prefWidth="333"/>
                        </VBox>
                        <VBox fx:id="stratagemHeader" visible="false" managed="false">
                            <Label text="Stratagem Name:"  styleClass="detachment_header"/>
                            <ListView fx:id="stratagemList" onMouseClicked="#stratagemListSelect" styleClass="detachment_list" prefWidth="333"/>
                        </VBox>
                        <VBox fx:id="enhancementHeader" visible="false" managed="false">
                            <Label text="Enhancement Name:" styleClass="detachment_header"/>
                            <ListView fx:id="enhancementList" onMouseClicked="#enhancementListSelect" styleClass="detachment_list" prefWidth="333"/>
                        </VBox>
                    </HBox>
                    <StackPane>
                        <StackPane fx:id="detachmentRulesView">
                            <VBox>
                                <Label fx:id="detachmentLabel" styleClass="detachment_header_big"/>
                                <VBox fx:id="dynamicVBox"/>
                            </VBox>
                        </StackPane>
                        <StackPane fx:id="detachmentStratagemView" visible="false">
                            <BorderPane>
                                <center>
                                    <VBox>
                                        <Label fx:id="stratagemID" styleClass="detachment_header"/>
                                        <Label fx:id="stratagemType" styleClass="detachment_header"/>
                                        <Label fx:id="stratagemCost" styleClass="detachment_header"/>
                                        <Label fx:id="stratagemPhase" styleClass="detachment_header"/>
                                        <WebView fx:id="stratagemRules" style="-fx-pref-height: 250;"/>
                                        <TextArea fx:id="stratagemLegend" wrapText="true" editable="false"/>
                                    </VBox>
                                </center>
                            </BorderPane>
                        </StackPane>
                        <StackPane fx:id="enhancementView" visible="false">
                            <BorderPane>
                                <center>
                                    <VBox>
                                        <Label fx:id="enhancementName" styleClass="detachment_header"/>
                                        <Label fx:id="enhancementCost" styleClass="detachment_header"/>
                                        <WebView fx:id="enhancementRules" style="-fx-pref-height: 250;"/>
                                        <TextArea fx:id="enhancementLegend" wrapText="true" editable="false"/>
                                    </VBox>
                                </center>
                            </BorderPane>
                        </StackPane>
                    </StackPane>
                </HBox>
            </VBox>

它产生这样的结果: FXML 元素大小调整

我已经阅读了 JavaFX 文档、几个专门介绍 JavaFX 的网站、这个论坛和 ChatGPT。我尝试在许多不同的父级和子级上添加各种修饰符,例如 prefHeight、maxHeight、minHeight、VBox.vgrow,但相关元素无济于事。我已经在其他地方成功使用过这些,所以我不确定我做错了什么。

这也完全有可能是一种蹩脚的构建 UI 的方式,我需要重构。

javafx fxml javafx-11
1个回答
0
投票

我希望第二个 HBox 中的元素填充屏幕的其余部分

首先请注意,

HBox
已经填满了屏幕的其余部分。如果您为其背景着色,您可以看到这一点,例如与
<HBox style='-fx-background-color:skyblue;'>

HBox

文档告诉您
HBox
的布局策略如何工作:

HBox
会将子项的大小(如果可调整大小)调整为他们喜欢的宽度...。 如果将
hbox
的大小调整为大于其首选宽度,则默认情况下它将保持子级的首选宽度,而未使用额外的空间。如果应用程序希望为一个或多个子进程分配额外的空间,则可以选择对子进程设置
hgrow
约束。有关详细信息,请参阅“可选布局约束”。

HBox
的两个子节点是另一个
HBox
和一个
StackPane
。当空间多于这些需要时,
HBox
会将它们调整为首选大小,并将其余空间留空。您可以通过设置
hgrow
约束为子节点分配额外空间,但您需要指定哪些节点获得额外空间。例如,要将其仅分配给
StackPane
,您可以将
HBox.hgrow="ALWAYS"
添加到
StackPane
的声明中:

<VBox fx:id="detachmentView">
    <HBox alignment="CENTER">
        <!-- ... -->
    </HBox>
    <Separator />
    <HBox>
        <HBox maxWidth="666">
            <!-- ... -->
        </HBox>
        <StackPane HBox.hgrow="ALWAYS">
            <!-- ... -->
        </StackPane>
    </HBox>
</VBox>

您可以使用

BorderPane
实现相同的目的:

<VBox fx:id="detachmentView">
    <HBox alignment="CENTER">
        <!-- ... -->
    </HBox>
    <Separator />
    <BorderPane>
        <left>
            <HBox maxWidth="666">
                <!-- ... -->
            </HBox>
        </left>
        <center>
            <StackPane>
                <!-- ... -->
            </StackPane>
        </center>
    </BorderPane>
</VBox>

这是有效的,因为

BorderPane
的布局策略为中心分配了额外的空间。再次参考文档

顶部和底部子项将调整到其首选高度并扩展边框窗格的宽度。左右子节点将调整为它们的首选宽度,并延长顶部和底部节点之间的长度。并且中心节点将调整大小以填充中间的可用空间。任何位置都可以为空。

在这种情况下,顶部、底部和右侧都是空的,因此它们占用的空间都是零。左侧的

<HBox>
采用其首选宽度,其余空间分配给
<StackPane>

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.