You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX FXML:如何让SubScene占满GridPane单元格区域?

解决SubScene自适应GridPane单元格尺寸的问题

要让3D SubScene自动适应GridPane所在单元格的宽高,无需硬编码尺寸,可通过以下步骤实现:

1. 调整GridPane的布局约束

首先补充并完善GridPane的行、列约束,明确各区域的布局行为:

<rowConstraints>
    <!-- 第1行:按钮行,高度固定 -->
    <RowConstraints vgrow="NEVER" />
    <!-- 第2行:滚动面板行,自动扩展填充剩余空间 -->
    <RowConstraints vgrow="ALWAYS" />
    <!-- 第3-6行:控件行,高度固定 -->
    <RowConstraints vgrow="NEVER" />
    <RowConstraints vgrow="NEVER" />
    <RowConstraints vgrow="NEVER" />
    <RowConstraints vgrow="NEVER" />
</rowConstraints>

<columnConstraints>
    <!-- 第一列:3D区域,自动扩展占满可用宽度 -->
    <ColumnConstraints hgrow="ALWAYS" fillWidth="true" />
    <!-- 右侧三列:控件列,宽度随内容自适应 -->
    <ColumnConstraints hgrow="NEVER" fillWidth="true" />
    <ColumnConstraints hgrow="NEVER" fillWidth="true" />
    <ColumnConstraints hgrow="NEVER" fillWidth="true" />
</columnConstraints>

2. 用容器包裹SubScene并绑定尺寸

SubScene本身不会自动填充父容器,因此将其放入StackPane(自动填充单元格空间),同时绑定SubScene的宽高到StackPane,并设置3D内容的缩放策略:

<!-- 替换原有的SubScene代码 -->
<StackPane GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.rowSpan="6">
    <SubScene fx:id="subscene" 
              resizePolicy="RESIZE_WITH_PARENT"
              prefWidth="${parent.width}"
              prefHeight="${parent.height}">
        <root>
            <Region />
        </root>
    </SubScene>
</StackPane>

关键设置说明:

  • resizePolicy="RESIZE_WITH_PARENT":让SubScene内的3D内容随SubScene尺寸变化自动缩放
  • prefWidth="${parent.width}"/prefHeight="${parent.height}":通过FXML绑定表达式,让SubScene的尺寸跟随父容器(StackPane)实时变化
  • StackPane:自动填充GridPane分配的单元格空间,作为SubScene的适配容器

3. 移除硬编码尺寸

删除原SubScene标签中的width="50"和height="50"属性,确保尺寸完全由布局约束和绑定控制。

修改后的完整FXML代码

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

<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.SubScene?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Box?>
<?import javafx.scene.PerspectiveCamera?>

<BorderPane fx:controller="Controller"
    xmlns:fx="http://javafx.com/fxml" styleClass="root">

    <top>
        <MenuBar>
            <menus>
                <Menu text="File">
                    <items>
                        <MenuItem text="New"
                            onAction="#handleNewSimulationAction" />
                        <MenuItem text="Save"
                            onAction="#handleSaveSimulationAction" />
                        <MenuItem text="Load"
                            onAction="#handleLoadSimulationAction" />
                    </items>
                </Menu>
            </menus>
        </MenuBar>
    </top>

    <center>
        <GridPane hgap="10" vgap="10">

            <rowConstraints>
                <RowConstraints vgrow="NEVER" />
                <RowConstraints vgrow="ALWAYS" />
                <RowConstraints vgrow="NEVER" />
                <RowConstraints vgrow="NEVER" />
                <RowConstraints vgrow="NEVER" />
                <RowConstraints vgrow="NEVER" />
            </rowConstraints>

            <columnConstraints>
                <ColumnConstraints hgrow="ALWAYS" fillWidth="true" />
                <ColumnConstraints hgrow="NEVER" fillWidth="true" />
                <ColumnConstraints hgrow="NEVER" fillWidth="true" />
                <ColumnConstraints hgrow="NEVER" fillWidth="true" />
            </columnConstraints>

            <gridLinesVisible>true</gridLinesVisible>

            <StackPane GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.rowSpan="6">
                <SubScene fx:id="subscene" 
                          resizePolicy="RESIZE_WITH_PARENT"
                          prefWidth="${parent.width}"
                          prefHeight="${parent.height}">
                    <root>
                        <Region />
                    </root>
                </SubScene>
            </StackPane>

            <Button text="Add" GridPane.columnIndex="1"
                GridPane.rowIndex="0" onAction="#handleAddAction" />

            <Button text="Edit" GridPane.columnIndex="2"
                GridPane.rowIndex="0" onAction="#handleEditAction" />

            <Button text="Delete" GridPane.columnIndex="3"
                GridPane.rowIndex="0" onAction="#handleDeleteAction" />

            <ScrollPane GridPane.columnIndex="1" GridPane.rowIndex="1"
                GridPane.columnSpan="3" />

            <Label text="Speed" GridPane.columnIndex="1"
                GridPane.rowIndex="2" />

            <Slider GridPane.columnIndex="2" GridPane.rowIndex="2"
                GridPane.columnSpan="2" />

            <Label text="Gravity" GridPane.columnIndex="1"
                GridPane.rowIndex="3" />

            <TextField GridPane.columnIndex="2" GridPane.rowIndex="3"
                GridPane.columnSpan="2" />

            <HBox GridPane.columnIndex="1" GridPane.rowIndex="4">
                <Button text="&lt;&lt;" onAction="#handleQuickRewindAction" />
                <Button text="&lt;" onAction="#handleRewindAction" />
            </HBox>

            <Text text="0.00" GridPane.columnIndex="2" GridPane.rowIndex="4" />

            <HBox GridPane.columnIndex="3" GridPane.rowIndex="4">
                <Button text="&gt;" onAction="#handleFastForwardAction" />
                <Button text="&gt;&gt;"
                    onAction="#handleQuickFastForwardAction" />
            </HBox>

            <Button text="Start" GridPane.columnIndex="2"
                GridPane.rowIndex="5" onAction="#handlePauseAction" />

        </GridPane>
    </center>

    <stylesheets>
        <URL value="@style.css" />
    </stylesheets>

</BorderPane>

调整完成后,SubScene会自动跟随GridPane第一列的单元格尺寸变化,窗口调整时也能实时自适应,无需硬编码任何尺寸值。

内容的提问来源于stack exchange,提问作者George

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 03:40:48