有没有一种方法可以将 javafx 中网格窗格中对象的格式(间距、填充等)与其他对象分开

问题描述 投票:0回答:1

所以我正在 javafx 上重新创建计算器的结构。不是为了功能,而是为了外观。我创建了按钮并将它们之间的水平和垂直间距设置为 16。但是,当我有一个文本字段对象来显示数字/结果(同样不是为了功能,而是为了显示)时,按钮会受到文本字段对象大小的影响。因此,我放置文本字段对象的第一行有一个巨大的间隙。

这是我该部分的代码:

        // layout manager: organize window contents
        GridPane root = new GridPane();
        
        // Scene: contains window content
        // parameters: layout manager; width window; height window
        Scene mainScene = new Scene(root, 600, 600);
        // attach/display Scene on Stage (window)
        mainStage.setScene( mainScene );
        
        // create TextField
        TextField nameField = new TextField("");
        root.add(nameField, 3, 1);
        
        root.setStyle( "-fx-font-size: 24;" );
        
        // to add space between rows and columns
        root.setHgap( 16 ); // between horizontal objects
        root.setVgap( 16 ); // between vertical objects
        
        // create all buttons
        Button button0 = new Button("0");
        Button button1 = new Button("1");
        Button button2 = new Button("2");
        Button button3 = new Button("3");
        Button button4 = new Button("4");
        ...
        
        // parameters: object, column # (X), row # (Y)
        // first row
        root.add(buttonAllClear, 3, 2);
        root.add(buttonClear, 4, 2);
        root.add(buttonDelete, 5, 2);
        root.add(buttonDivides, 6, 2);
    
        // second row
        root.add(button7, 3, 3);
        root.add(button8, 4, 3);
        root.add(button9, 5, 3);
        root.add(buttonTimes, 6, 3);
        // 
    //when I run the code i get:
    //[    text field       ]
    //ac                    c    del    /
    //7                     8    9     *
    //4                     5    6     -
    //1                     2    3     +
    //0                     .    =

//but i want: 
//[    text field       ]
//ac     c     del   /
//7      8     9     *
//4      5     6     -
//1      2     3     +
//0      .     =
    
java button javafx textfield gridpane
1个回答
0
投票

使用 TextField 跨越多列

您可以在 columnSpan

 中的节点上设置 
GridPane
,使其跨越定义的列数。

仅将 GridPane 用于按钮

或者,您无法将计算器的文本字段放置在网格中,而是使用一个包含文本字段和按钮网格的 VBox。

示例

此示例演示了两种方法,使用

columnSpan
作为等于按钮,并将文本字段放置在
VBox
中的单独行中。

calc

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.Arrays;

public class CalcApp extends Application {
    @Override
    public void start(Stage stage) {
        String[][] buttonText = {
                {"ac", "c", "del", "/"},
                { "7", "8", "9",   "*"},
                { "4", "5", "6",   "-"},
                { "1", "2", "3",   "+"},
                { "1", "2", "="}
        };

        GridPane buttonGrid = new GridPane(5, 5);

        for (int r = 0; r < buttonText.length; r++) {
            String[] rowText = buttonText[r];
            Button[] buttonsInRow =
                    Arrays.stream(rowText)
                            .map(CalcApp::createButton)
                            .toArray(Button[]::new);

            buttonGrid.addRow(r, buttonsInRow);
        }

        buttonGrid.getChildren().stream()
                .filter(CalcApp::isEqualsButton)
                .forEach(equalsButton ->
                        GridPane.setColumnSpan(
                                equalsButton,
                                2
                        )
                );

        int nCols = buttonText[0].length;
        for (int c = 0; c < nCols; c++) {
            ColumnConstraints columnConstraints = new ColumnConstraints();
            columnConstraints.setPercentWidth(100.0 / nCols);
            buttonGrid.getColumnConstraints().add(columnConstraints);
        }

        TextField textField = new TextField();
        textField.setStyle("-fx-font-size: 20px;");
        textField.setMinHeight(TextField.USE_PREF_SIZE);

        VBox layout = new VBox(10, textField, buttonGrid);
        layout.setPadding(new Insets(10));
        VBox.setVgrow(buttonGrid, Priority.SOMETIMES);

        stage.setScene(new Scene(layout));
        stage.show();
    }

    private static boolean isEqualsButton(Node n) {
        return n instanceof Button b && "=".equals(b.getText());
    }

    private static Button createButton(String text) {
        Button button = new Button(text);
        button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        button.setMinSize(Button.USE_PREF_SIZE, Button.USE_PREF_SIZE);
        GridPane.setVgrow(button, Priority.ALWAYS);
        GridPane.setHgrow(button, Priority.ALWAYS);
        button.setStyle("-fx-font-size: 20px;");

        return button;
    }

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

替代方案:使用 TilePane

类似的解决方案使用

TilePane
而不是
GridPane
,但将
TextField
保留在包含按钮的
TilePane
之外。

© www.soinside.com 2019 - 2024. All rights reserved.