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

JavaFX计算器窗口缩放问题:固定最小尺寸与按钮自适应

计算器窗口尺寸与按钮自适应问题解决

问题描述

我用Scene Builder制作了一款计算器原型,在376x752的固定尺寸下运行完全正常,但调整窗口大小时遇到两个问题:

  1. 如何设置窗口不能小于该固定尺寸?
  2. 最大化窗口时,包含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的锚点实现了横向拉伸,但按钮未跟随放大,是因为缺少三个关键配置:

  1. 给GridPane的列约束设置百分比宽度和自动扩展属性
  2. 取消按钮的固定宽度限制,允许按钮填满所在列
  3. 移除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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:00:54