JavaFX计算器窗口缩放问题:固定最小尺寸与按钮自适应
计算器窗口尺寸与按钮自适应问题解决
问题描述
我用Scene Builder制作了一款计算器原型,在376x752的固定尺寸下运行完全正常,但调整窗口大小时遇到两个问题:
- 如何设置窗口不能小于该固定尺寸?
- 最大化窗口时,包含Label的VBox已横向填满屏幕,但操作按钮仍停留在原位置,如何让按钮放大填充新增的横向空间(实现类似Windows计算器的行为)?我已尝试修改GridPane的行百分比宽度和hgrow属性,但未生效。
原FXML代码:
<AnchorPane minHeight="752.0" minWidth="376.0" style="-fx-background-color: #17181a;" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="muri.calc.HelloController"> <VBox alignment="BOTTOM_RIGHT" layoutX="34.0" layoutY="138.0" minHeight="130.0" minWidth="312.0" AnchorPane.leftAnchor="34.0" AnchorPane.rightAnchor="32.0"> <children> <Label fx:id="resultadoTexto" alignment="CENTER" contentDisplay="CENTER" text="82" textAlignment="RIGHT" textFill="WHITE"> <font> <Font size="48.0" /> </font> </Label> </children> </VBox> <!-- Grid for Buttons --> <GridPane hgap="20" layoutX="32" layoutY="670" prefWidth="310.0" vgap="14" AnchorPane.bottomAnchor="32.0" AnchorPane.leftAnchor="34.0" AnchorPane.rightAnchor="32.0"> <Button fx:id="quadradoBotao" minHeight="62.0" minWidth="62.0" mnemonicParsing="false" prefHeight="62.0" prefWidth="62.0" text="n²" GridPane.columnIndex="2" GridPane.rowIndex="1" /> <Button fx:id="porcentBotao" minHeight="62.0" minWidth="62.0" mnemonicParsing="false" prefHeight="62.0" prefWidth="62.0" text="%" GridPane.columnIndex="1" GridPane.rowIndex="1" /> <Button fx:id="raizBotao" minHeight="62.0" minWidth="62.0" mnemonicParsing="false" prefHeight="62.0" prefWidth="62.0" text="√" GridPane.rowIndex="1" /> <!-- First Row --> <Button fx:id="acBotao" minHeight="31.0" minWidth="62" text="Ac" /> <Button fx:id="dividirBotao" minHeight="62" minWidth="62" text="/" GridPane.columnIndex="3" GridPane.rowIndex="1" /> <Button fx:id="multiplicarBotao" minHeight="62" minWidth="62" text="*" textAlignment="JUSTIFY" GridPane.columnIndex="3" GridPane.rowIndex="2" /> <Button fx:id="subtrairBotao" minHeight="62.0" minWidth="62" prefHeight="63.0" prefWidth="63.0" text="-" GridPane.columnIndex="3" GridPane.rowIndex="3" /> <!-- Second Row --> <Button fx:id="seteBotao" minHeight="62" minWidth="62" text="7" GridPane.rowIndex="2" /> <Button fx:id="oitoBotao" minHeight="62" minWidth="62" text="8" GridPane.columnIndex="1" GridPane.rowIndex="2" /> <Button fx:id="noveBotao" minHeight="62" minWidth="62" text="9" GridPane.columnIndex="2" GridPane.rowIndex="2" /> <!-- Third Row --> <Button fx:id="quatroBotao" minHeight="62" minWidth="62" text="4" GridPane.rowIndex="3" /> <Button fx:id="cincoBotao" minHeight="62" minWidth="62" text="5" GridPane.columnIndex="1" GridPane.rowIndex="3" /> <Button fx:id="seisBotao" minHeight="62" minWidth="62" text="6" GridPane.columnIndex="2" GridPane.rowIndex="3" /> <Button fx:id="somarBotao" minHeight="62.0" minWidth="62" text="+" GridPane.columnIndex="3" GridPane.rowIndex="4" /> <!-- Fourth Row --> <Button fx:id="umBotao" minHeight="62" minWidth="62" text="1" GridPane.rowIndex="4" /> <Button fx:id="doisBotao" minHeight="62" minWidth="62" text="2" GridPane.columnIndex="1" GridPane.rowIndex="4" /> <Button fx:id="tresBotao" minHeight="62" minWidth="62" text="3" GridPane.columnIndex="2" GridPane.rowIndex="4" /> <!-- Fifth Row --> <Button fx:id="alterarBotao" minHeight="62" minWidth="62" text="+/-" GridPane.rowIndex="5" /> <Button fx:id="zeroBotao" minHeight="62" minWidth="62" text="0" GridPane.columnIndex="1" GridPane.rowIndex="5" /> <Button fx:id="decimalBotao" minHeight="62" minWidth="62" text="." GridPane.columnIndex="2" GridPane.rowIndex="5" /> <Button fx:id="igualBotao" minHeight="62.0" minWidth="62" text="=" GridPane.columnIndex="3" GridPane.rowIndex="5" /> <Button fx:id="apagarBotao" layoutX="258.0" layoutY="54.0" minHeight="31.0" minWidth="62" prefHeight="31.0" prefWidth="62.0" text="⌫" GridPane.columnIndex="3" /> <columnConstraints> <ColumnConstraints /> <ColumnConstraints /> <ColumnConstraints /> <ColumnConstraints /> </columnConstraints> <rowConstraints> <RowConstraints /> <RowConstraints /> <RowConstraints /> <RowConstraints /> <RowConstraints /> <RowConstraints /> <RowConstraints /> </rowConstraints> </GridPane> </AnchorPane>
解决方案
问题1:限制窗口最小尺寸
窗口的最小尺寸需要在**Stage(主窗口)**层面设置,仅在AnchorPane上设置minWidth/minHeight不够。在启动类或控制器中添加以下代码:
primaryStage.setMinWidth(376); primaryStage.setMinHeight(752);
如果用纯FXML配置,也可以在SceneBuilder的Scene属性面板中直接设置minWidth和minHeight,确保Stage不会覆盖这些参数。
问题2:实现按钮横向自适应填充
GridPane已经通过AnchorPane的锚点实现了横向拉伸,但按钮未跟随放大,是因为缺少三个关键配置:
- 给GridPane的列约束设置百分比宽度和自动扩展属性
- 取消按钮的固定宽度限制,允许按钮填满所在列
- 移除GridPane的固定prefWidth,让它完全由锚点控制
修改后的完整FXML代码:
<AnchorPane minHeight="752.0" minWidth="376.0" style="-fx-background-color: #17181a;" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="muri.calc.HelloController"> <VBox alignment="BOTTOM_RIGHT" layoutX="34.0" layoutY="138.0" minHeight="130.0" AnchorPane.leftAnchor="34.0" AnchorPane.rightAnchor="32.0"> <children> <Label fx:id="resultadoTexto" alignment="CENTER" contentDisplay="CENTER" text="82" textAlignment="RIGHT" textFill="WHITE"> <font> <Font size="48.0" /> </font> </Label> </children> </VBox> <!-- Grid for Buttons --> <GridPane hgap="20" layoutY="670" vgap="14" AnchorPane.bottomAnchor="32.0" AnchorPane.leftAnchor="34.0" AnchorPane.rightAnchor="32.0"> <Button fx:id="quadradoBotao" minHeight="62.0" mnemonicParsing="false" prefHeight="62.0" maxWidth="Infinity" text="n²" GridPane.columnIndex="2" GridPane.rowIndex="1" /> <Button fx:id="porcentBotao" minHeight="62.0" mnemonicParsing="false" prefHeight="62.0" maxWidth="Infinity" text="%" GridPane.columnIndex="1" GridPane.rowIndex="1" /> <Button fx:id="raizBotao" minHeight="62.0" mnemonicParsing="false" prefHeight="62.0" maxWidth="Infinity" text="√" GridPane.rowIndex="1" /> <!-- First Row --> <Button fx:id="acBotao" minHeight="31.0" maxWidth="Infinity" text="Ac" /> <Button fx:id="dividirBotao" minHeight="62" maxWidth="Infinity" text="/" GridPane.columnIndex="3" GridPane.rowIndex="1" /> <Button fx:id="multiplicarBotao" minHeight="62" maxWidth="Infinity" text="*" textAlignment="JUSTIFY" GridPane.columnIndex="3" GridPane.rowIndex="2" /> <Button fx:id="subtrairBotao" minHeight="62.0" prefHeight="63.0" maxWidth="Infinity" text="-" GridPane.columnIndex="3" GridPane.rowIndex="3" /> <!-- Second Row --> <Button fx:id="seteBotao" minHeight="62" maxWidth="Infinity" text="7" GridPane.rowIndex="2" /> <Button fx:id="oitoBotao" minHeight="62" maxWidth="Infinity" text="8" GridPane.columnIndex="1" GridPane.rowIndex="2" /> <Button fx:id="noveBotao" minHeight="62" maxWidth="Infinity" text="9" GridPane.columnIndex="2" GridPane.rowIndex="2" /> <!-- Third Row --> <Button fx:id="quatroBotao" minHeight="62" maxWidth="Infinity" text="4" GridPane.rowIndex="3" /> <Button fx:id="cincoBotao" minHeight="62" maxWidth="Infinity" text="5" GridPane.columnIndex="1" GridPane.rowIndex="3" /> <Button fx:id="seisBotao" minHeight="62" maxWidth="Infinity" text="6" GridPane.columnIndex="2" GridPane.rowIndex="3" /> <Button fx:id="somarBotao" minHeight="62.0" maxWidth="Infinity" text="+" GridPane.columnIndex="3" GridPane.rowIndex="4" /> <!-- Fourth Row --> <Button fx:id="umBotao" minHeight="62" maxWidth="Infinity" text="1" GridPane.rowIndex="4" /> <Button fx:id="doisBotao" minHeight="62" maxWidth="Infinity" text="2" GridPane.columnIndex="1" GridPane.rowIndex="4" /> <Button fx:id="tresBotao" minHeight="62" maxWidth="Infinity" text="3" GridPane.columnIndex="2" GridPane.rowIndex="4" /> <!-- Fifth Row --> <Button fx:id="alterarBotao" minHeight="62" maxWidth="Infinity" text="+/-" GridPane.rowIndex="5" /> <Button fx:id="zeroBotao" minHeight="62" maxWidth="Infinity" text="0" GridPane.columnIndex="1" GridPane.rowIndex="5" /> <Button fx:id="decimalBotao" minHeight="62" maxWidth="Infinity" text="." GridPane.columnIndex="2" GridPane.rowIndex="5" /> <Button fx:id="igualBotao" minHeight="62.0" maxWidth="Infinity" text="=" GridPane.columnIndex="3" GridPane.rowIndex="5" /> <Button fx:id="apagarBotao" minHeight="31.0" prefHeight="31.0" maxWidth="Infinity" text="⌫" GridPane.columnIndex="3" /> <columnConstraints> <ColumnConstraints percentWidth="25" hgrow="ALWAYS" /> <ColumnConstraints percentWidth="25" hgrow="ALWAYS" /> <ColumnConstraints percentWidth="25" hgrow="ALWAYS" /> <ColumnConstraints percentWidth="25" hgrow="ALWAYS" /> </columnConstraints> <rowConstraints> <RowConstraints /> <RowConstraints /> <RowConstraints /> <RowConstraints /> <RowConstraints /> <RowConstraints /> <RowConstraints /> </rowConstraints> </GridPane> </AnchorPane>
关键修改说明:
- 移除GridPane的
prefWidth,让它完全依赖AnchorPane的锚点实现横向拉伸 - 给每个
ColumnConstraints添加percentWidth="25"和hgrow="ALWAYS",确保4列均分宽度并自动扩展 - 所有按钮移除
minWidth和prefWidth,添加maxWidth="Infinity",允许按钮填满所在列的宽度 - 保留按钮的
minHeight,保证窗口缩小时按钮不会过度压缩
内容的提问来源于stack exchange,提问作者Murilo
相关产品推荐
相关产品推荐

