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="<<" onAction="#handleQuickRewindAction" /> <Button text="<" onAction="#handleRewindAction" /> </HBox> <Text text="0.00" GridPane.columnIndex="2" GridPane.rowIndex="4" /> <HBox GridPane.columnIndex="3" GridPane.rowIndex="4"> <Button text=">" onAction="#handleFastForwardAction" /> <Button text=">>" 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
相关产品推荐
相关产品推荐

