【问题标题】:JavaFX button sizing - HBox and VBox don't align properly and gaps visibleJavaFX 按钮大小调整 - HBox 和 VBox 未正确对齐并且间隙可见
【发布时间】:2018-10-15 12:18:03
【问题描述】:

我正在尝试学习 JavaFX,我正在构建一个计算器,并且我遇到了一些需要指导的按钮大小行为。

首先,为什么包含零和点按钮的 HBox 在右侧似乎有几个像素? https://imgur.com/a/faAEJm6

其次,我怎样才能让等号按钮在它所在的 HBox 内或多或少地占据水平空间?我试过设置它的首选宽度方法,但这没有区别。我想我的问题与空间有限时节点的大小有关。

完整的课程如下。我所做的是为每一行数字按钮和点按钮创建一个 HBox。然后将这三行放置在一个 VBox 中,该 VBox 放置在等号按钮旁边的 HBox 中。

我正在阅读 JavaFX for Dummies,并查看了许多帖子等,但无法解决!

package calculator;

import javafx.application.*;
import static javafx.application.Application.launch;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;

public class UserInterface extends Application {

    static int buttonHeight = 30;
    VBox pane;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

//4, 5, 6 numeric buttons 
        //Six button
        Button b6 = new Button("6");
        b6.setMaxWidth(Double.MAX_VALUE);
        b6.setPrefHeight(b6.getPrefHeight() + buttonHeight);
        HBox.setHgrow(b6, Priority.ALWAYS);

        //Five button
        Button b5 = new Button("5");
        b5.setMaxWidth(Double.MAX_VALUE);
        b5.setPrefHeight(b5.getPrefHeight() + buttonHeight);
        HBox.setHgrow(b5, Priority.ALWAYS);

        //Four button
        Button b4 = new Button("4");
        b4.setMaxWidth(Double.MAX_VALUE);
        b4.setPrefHeight(b4.getPrefHeight() + buttonHeight);
        HBox.setHgrow(b4, Priority.ALWAYS);

        //Place the buttons in the 456 HBox
        HBox row456 = new HBox();
        row456.getChildren().addAll(b4, b5, b6);

//1, 2, 3 numeric buttons
        //Button three
        Button b3 = new Button("3");
        b3.setMaxWidth(Double.MAX_VALUE);
        b3.setPrefHeight(b3.getPrefHeight() + buttonHeight);
        HBox.setHgrow(b3, Priority.ALWAYS);

        //Button two
        Button b2 = new Button("2");
        b2.setMaxWidth(Double.MAX_VALUE);
        b2.setPrefHeight(b2.getPrefHeight() + buttonHeight);
        HBox.setHgrow(b2, Priority.ALWAYS);

        //Button one
        Button b1 = new Button("1");
        b1.setMaxWidth(Double.MAX_VALUE);
        b1.setPrefHeight(b1.getPrefHeight() + buttonHeight);
        HBox.setHgrow(b1, Priority.ALWAYS);

        //Place the buttons in the 123 HBox
        HBox row123 = new HBox();
        row123.getChildren().addAll(b1, b2, b3);

//Zero and point buttons
        //zero button
        Button zero = new Button("0");
        zero.setMaxWidth(Double.MAX_VALUE);
        zero.setPrefHeight(zero.getPrefHeight() + buttonHeight);
        HBox.setHgrow(zero, Priority.ALWAYS);

        //point button
        Button point = new Button(".");
        point.setMaxWidth(Double.MAX_VALUE);
        point.setPrefHeight(point.getPrefHeight() + buttonHeight);
        HBox.setHgrow(point, Priority.ALWAYS);

        //Place the buttons in the zeroPoint HBox
        HBox zeroPoint = new HBox();
        zeroPoint.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(zeroPoint, Priority.ALWAYS);
        zeroPoint.getChildren().addAll(zero, point);


//Numeric button rows in a VBox
        VBox intLower = new VBox(row456, row123, zeroPoint);
        HBox.setHgrow(intLower, Priority.ALWAYS);


//Equals button
        Button equals = new Button("=");
        HBox.setHgrow(equals, Priority.ALWAYS);
        equals.setMaxWidth(Double.MAX_VALUE);
        equals.setMaxHeight(Double.MAX_VALUE);

// Numeric button VBox and  equals button inside HBox
        HBox lower = new HBox(intLower, equals);
        lower.setAlignment(Pos.BOTTOM_CENTER);


//Populate the root pane
        pane = new VBox();
        pane.getChildren().addAll(lower);
        pane.setAlignment(Pos.BOTTOM_CENTER);

//Add the root pane to a scene
        Scene scene = new Scene(pane, 210, 285);
        // Finish and show the stage
        primaryStage.setResizable(false);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Calculator");
        primaryStage.show();

    }
}

编辑: 我现在尝试使用 GridPane 来组装这个 GUI,并且遇到了同样的问题,即行没有正确对齐并且节点之间的小空间可见 - 看起来当你拿最便宜的报价来翻新厨房然后发现没有橱柜齐平:https://imgur.com/a/lXUbHIv

package calculator;

import javafx.application.*;
import static javafx.application.Application.launch;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;

public class UserInterface extends Application {

    private static int butHeightModifier = 30;
    private static int appWidth = 225 * 2;
    private static int appHeight = 310 * 2;
    private static int numRows = 7;
    private static int numCols = 5;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
//7, 8, 9 numeric buttons 
        //Nine button
        Button b9 = new Button("9");
        b9.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(b9, Priority.ALWAYS);
        VBox.setVgrow(b9, Priority.ALWAYS);

        //Eight button
        Button b8 = new Button("8");
        b8.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(b8, Priority.ALWAYS);
        VBox.setVgrow(b8, Priority.ALWAYS);

        //Seven button
        Button b7 = new Button("7");
        b7.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(b7, Priority.ALWAYS);
        VBox.setVgrow(b7, Priority.ALWAYS);

        //Place the buttons in the 456 HBox
        HBox row789 = new HBox();
        row789.getChildren().addAll(b7, b8, b9);

//4, 5, 6 numeric buttons 
        //Six button
        Button b6 = new Button("6");
        b6.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(b6, Priority.ALWAYS);
        VBox.setVgrow(b6, Priority.ALWAYS);

        //Five button
        Button b5 = new Button("5");
        b5.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(b5, Priority.ALWAYS);
        VBox.setVgrow(b5, Priority.ALWAYS);

        //Four button
        Button b4 = new Button("4");
        b4.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(b4, Priority.ALWAYS);
        VBox.setVgrow(b4, Priority.ALWAYS);

        //Place the buttons in the 456 HBox
        HBox row456 = new HBox();
        row456.getChildren().addAll(b4, b5, b6);

//1, 2, 3 numeric buttons
        //Button three
        Button b3 = new Button("3");
        b3.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(b3, Priority.ALWAYS);
        VBox.setVgrow(b3, Priority.ALWAYS);

        //Button two
        Button b2 = new Button("2");
        b2.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(b2, Priority.ALWAYS);
        VBox.setVgrow(b2, Priority.ALWAYS);

        //Button one
        Button b1 = new Button("1");
        b1.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(b1, Priority.ALWAYS);
        VBox.setVgrow(b1, Priority.ALWAYS);

        //Place the buttons in the 123 HBox
        HBox row123 = new HBox();
        row123.getChildren().addAll(b1, b2, b3);

//Zero and point buttons
        //zero button
        Button zero = new Button("0");
        zero.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(zero, Priority.ALWAYS);
        VBox.setVgrow(zero, Priority.ALWAYS);

        //point button
        Button point = new Button(".");
        point.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(point, Priority.ALWAYS);
        VBox.setVgrow(point, Priority.ALWAYS);

        //Place the buttons in the zeroPoint HBox
        HBox zeroPoint = new HBox();
        zeroPoint.getChildren().addAll(zero, point);

//Multiply and division buttons
        Button multiply = new Button("X");
        multiply.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(multiply, Priority.ALWAYS);
        VBox.setVgrow(multiply, Priority.ALWAYS);

        Button division = new Button("/");
        division.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(division, Priority.ALWAYS);
        VBox.setVgrow(division, Priority.ALWAYS);

        //Place the buttons in the zeroPoint HBox
        HBox multiDiv = new HBox();
        multiDiv.getChildren().addAll(multiply, division);

//Plus and minus buttons
        Button plus = new Button("+");
        plus.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(plus, Priority.ALWAYS);
        VBox.setVgrow(plus, Priority.ALWAYS);

        Button minus = new Button("-");
        minus.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        HBox.setHgrow(minus, Priority.ALWAYS);
        VBox.setVgrow(minus, Priority.ALWAYS);

        //Place the buttons in the zeroPoint HBox
        HBox plusMinus = new HBox();
        plusMinus.getChildren().addAll(plus, minus);

//Equals button
        Button equals = new Button("=");
        equals.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);

// Create GridPane
        GridPane grid = new GridPane();

// Set row and column constraints
        ColumnConstraints col = new ColumnConstraints();
        col.setPercentWidth(20);
        grid.getColumnConstraints().addAll(col, col, col, col, col);

        RowConstraints row = new RowConstraints();
        row.setPercentHeight(14.2857);
        grid.getRowConstraints().addAll(row, row, row, row, row, row, row);

//Set filling constraint
        for (int r = 0; r <= numRows; r++) {
            RowConstraints rc = new RowConstraints();
            rc.setFillHeight(true);
            rc.setVgrow(Priority.ALWAYS);
            grid.getRowConstraints().add(rc);
        }
        for (int c = 0; c <= numCols; c++) {
            ColumnConstraints cc = new ColumnConstraints();
            cc.setFillWidth(true);
            cc.setHgrow(Priority.ALWAYS);
            grid.getColumnConstraints().add(cc);
        }

//Add nodes to grid pane
        grid.add(zeroPoint, 0, 6, 3, 1);
        grid.add(equals, 3, 5, 2, 2);
        grid.add(row123, 0, 5, 3, 1);
        grid.add(row456, 0, 4, 3, 1);
        grid.add(row789, 0, 3, 3, 1);
        grid.add(multiDiv, 3, 4, 2, 1);
        grid.add(plusMinus, 3, 3, 2, 1);

// Create the scene and the stage
        Scene scene = new Scene(grid);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Calculator");
        primaryStage.setMinWidth(appWidth);
        primaryStage.setMinHeight(appHeight);
        primaryStage.setResizable(false);
        primaryStage.show();
    }
}

【问题讨论】:

  • 对于Buttons 使用GridPane 可能更好。
  • 我一定会试一试 GridPane - 我还没有读过那一章。但我还是想知道为什么 HBox/VBox 组合会这样。
  • 我创建了一个 GridPane 布局,但除非您遇到新问题,否则我将推迟发布它。
  • 另外,我个人会使用SceneBuilder 进行静态布局。
  • 好的,谢谢您的建议。我会进行实验,有任何问题都会回来。

标签: button javafx layout-manager vbox hbox


【解决方案1】:

GridLines 正在显示,以便您可以看到 Buttons 的情况,例如等号和小数点按钮。

等号按钮超过一行,小数按钮超过一列

buttonLayout.add(buttonList.get(11), 3, 0, 1, 4);//Equal Button
buttonLayout.add(buttonList.get(10), 1, 3, 2, 1);//Decimal Button

添加(节点子,int columnIndex,int rowIndex,int colspan,int rowspan) 在网格窗格的指定列、行位置和跨度处添加一个子项。

此代码允许Buttons 填充Cells代码来自here

    for (int rowIndex = 0; rowIndex < 4; rowIndex++) {
        RowConstraints rc = new RowConstraints();
        rc.setVgrow(Priority.ALWAYS) ; // allow row to grow
        rc.setFillHeight(true); // ask nodes to fill height for row
        // other settings as needed...
        buttonLayout.getRowConstraints().add(rc);
    }
    for (int colIndex = 0; colIndex < 4; colIndex++) {
        ColumnConstraints cc = new ColumnConstraints();
        cc.setHgrow(Priority.ALWAYS) ; // allow column to grow
        cc.setFillWidth(true); // ask nodes to fill space for column
        // other settings as needed...
        buttonLayout.getColumnConstraints().add(cc);
    }

完整代码:

import java.util.ArrayList;
import java.util.List;
import javafx.application.*;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;

public class UserInterface extends Application {

    VBox root = new VBox();
    MenuBar menuBar = new MenuBar();
    TextField display = new TextField("");
    List<Button> buttonList = new ArrayList();
    GridPane buttonLayout = new GridPane();


    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage){

        for(int i = 0; i < 10; i++)
        {
            Button tempButton = new Button(Integer.toString(i));            
            buttonList.add(tempButton);
        }        
        buttonList.add(new Button("."));
        buttonList.add(new Button("="));    


        for(int i = 0; i < buttonList.size(); i++)
        {
            buttonList.get(i).setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        }

        buttonLayout.add(buttonList.get(7), 0, 0);
        buttonLayout.add(buttonList.get(8), 1, 0);
        buttonLayout.add(buttonList.get(9), 2, 0);
        buttonLayout.add(buttonList.get(11), 3, 0, 1, 4);


        buttonLayout.add(buttonList.get(4), 0, 1);
        buttonLayout.add(buttonList.get(5), 1, 1);
        buttonLayout.add(buttonList.get(6), 2, 1);

        buttonLayout.add(buttonList.get(1), 0, 2);
        buttonLayout.add(buttonList.get(2), 1, 2);
        buttonLayout.add(buttonList.get(3), 2, 2);

        buttonLayout.add(buttonList.get(0), 0, 3);
        buttonLayout.add(buttonList.get(10), 1, 3, 2, 1);


        buttonLayout.setGridLinesVisible(true);
        buttonLayout.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        for (int rowIndex = 0; rowIndex < 4; rowIndex++) {
            RowConstraints rc = new RowConstraints();
            rc.setVgrow(Priority.ALWAYS) ; // allow row to grow
            rc.setFillHeight(true); // ask nodes to fill height for row
            // other settings as needed...
            buttonLayout.getRowConstraints().add(rc);
        }
        for (int colIndex = 0; colIndex < 4; colIndex++) {
            ColumnConstraints cc = new ColumnConstraints();
            cc.setHgrow(Priority.ALWAYS) ; // allow column to grow
            cc.setFillWidth(true); // ask nodes to fill space for column
            // other settings as needed...
            buttonLayout.getColumnConstraints().add(cc);
        }

        VBox.setVgrow(buttonLayout, Priority.ALWAYS);
        root.getChildren().addAll(display, buttonLayout);


        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();        
    }
}

【讨论】:

  • 谢谢。当我单独使用 GridPane 时,按钮会正确对齐。但是,如果我需要两个按钮跨越三个单元格怎么办?这不需要HBox吗?我真的很想知道为什么 HBox 无法对齐。 Button、HBox 和 GridPane 都是节点——说到对齐,难道不应该一视同仁吗?
  • 我在我的示例中特别指出了两种情况,其中列或行跨越多个。等号按钮跨度为 4 行,小数按钮跨度为 2。
  • 我明白了。我的问题是如何让 2 个按钮跨越 3 个单元格。我现在意识到这可以通过将列数加倍并让每个按钮占据 3 个单元格来实现,但这仍然不能解释为什么 HBox 无法对齐。我并不是要贬低您的解决方案,因为它有效,但我也想尝试了解 HBox 和 VBox 的行为方式。
  • 不幸的是,我不想通过你的代码来弄清楚。根据您的原始图片,我认为您的布局应该有一个HBox 作为根。您应该已将 VBoxButton(Equal Button) 添加到根目录。在您的VBox 中,您应该将您的三个HBox 添加到Buttons。这种布局应该可以解决您的差距问题。
猜你喜欢
  • 1970-01-01
  • 2017-09-04
  • 1970-01-01
  • 2012-04-23
  • 2021-09-24
  • 2020-02-12
  • 2015-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多