使用 GridPane 为不同行中的每个单元格实现唯一的列宽度?

Bra*_*ggs 6 java user-interface javafx

JavaFx我正在尝试使用以下方法对信用卡数据进行建模GridPane

我的模型包含 3 行(注意:每个字段由标签 + 文本字段组成):

第 1 行:名字和姓氏(4 个字段)

第 2 行:信用卡号(2 个字段)

第 3 行:到期日期 - 月、年 + CVV(6 个字段)

请参阅下面的屏幕截图:

卡数据模型

我正在阅读本教程,其中指出:

同一行中的所有单元格将具有相同的高度,同一列中的所有单元格将具有相同的宽度。不同的行可以有不同的高度,不同的列可以有不同的宽度。

是否有任何解决方法可以在 a 中逐行拥有不同大小的列GridPane

Obo*_*boe 8

对于图像中的特定布局,我将使用VBoxwithHBox来表示行:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.geometry.Insets;
import javafx.geometry.Pos;

public class App extends Application {

    @Override
    public void start(Stage stage) {

        Label lblFirst = new Label("First");
        Label lblLast = new Label("Last");
        Label lblNumber = new Label("Card Number");
        Label lblMonth = new Label("Month");
        Label lblYear = new Label("Year");
        Label lblCVV = new Label("CVV");
        
        TextField txtFirst = new TextField();
        TextField txtLast = new TextField();
        TextField txtNumber = new TextField();
        TextField txtMonth = new TextField();
        TextField txtYear = new TextField();
        TextField txtCVV = new TextField();

        HBox row1 = new HBox(10);
        HBox row2 = new HBox(10);
        HBox row3 = new HBox(10);
        
        row1.getChildren().add(createCell(lblFirst, txtFirst));
        row1.getChildren().add(createCell(lblLast, txtLast));
        
        row2.getChildren().add(createCell(lblNumber, txtNumber));
        
        row3.getChildren().add(createCell(lblMonth, txtMonth));
        row3.getChildren().add(createCell(lblYear, txtYear));
        row3.getChildren().add(createCell(lblCVV, txtCVV));
        
        VBox rows = new VBox(10, row1, row2, row3);
        
        StackPane.setMargin(rows, new Insets(10));
        
        StackPane root = new StackPane(rows);

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();
    }

    private static HBox createCell(Label label, TextField text) {
        HBox pane = new HBox(5, label, text);
        label.setMinWidth(Pane.USE_PREF_SIZE);
        text.setMinWidth(50);
        pane.setAlignment(Pos.CENTER);
        HBox.setHgrow(pane, Priority.ALWAYS);
        HBox.setHgrow(text, Priority.ALWAYS);
        return pane;
    }

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

}
Run Code Online (Sandbox Code Playgroud)

输出:


Sai*_*dem 5

+1 @JamesD 建议和 @Oboe 答案。理想情况下,我会将每一行布局分开,以便以简单的方式处理它,而不是仅使用一个 GridPane 使其变得复杂。

话虽如此,如果您想使用或了解如何使用一个 GridPane 进行类似的布局,下面的实现可能会给您一个快速的想法。

首先将您的布局分成所需的列,以计算出您总共需要多少列。(如下图所示)

在此输入图像描述

现在您将知道哪个节点将位于哪一列以及它将占据多少列(colspan)

我将针对一个节点进行解释:

假设您要插入名字字段。如果您在图中注意到,它位于 rowIndex: 0、columnIndex: 1 中,并且占据 4 列,因此 colSpan 值为 4。这里我们没有合并任何行,因此 rowSpan 值将始终为 1。

pane.add(getField(), 1, 0, 4, 1); // node, colIndex, rowIndex, colSpan, rowSpan
Run Code Online (Sandbox Code Playgroud)

同样,您可以关联其余节点的布局。为了更精确,您可以使用 ColumnConstraints 设置每列的首选宽度。以下是布局和约束的完整代码:

在此输入图像描述

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class CreditCardPaneDemo extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        VBox root = new VBox();
        root.setPadding(new Insets(5));
        root.setSpacing(10);
        Scene scene = new Scene(root,300,200);
        stage.setScene(scene);
        stage.setTitle("CreditCard");
        stage.show();

        GridPane pane = new GridPane();
        pane.setStyle("-fx-border-color:black;-fx-border-width:1px;-fx-background-color:yellow");
        pane.setPadding(new Insets(5));
        pane.setHgap(5);
        pane.setVgap(5);

        pane.add(getLabel("First"), 0, 0, 1, 1);
        pane.add(getField(), 1, 0, 4, 1);
        pane.add(getLabel("Last"), 5, 0, 1, 1);
        pane.add(getField(), 6, 0, 2, 1);

        pane.add(getLabel("Card Number"), 0, 1, 3, 1);
        pane.add(getField(), 3, 1, 5, 1);

        pane.add(getLabel("Month"), 0, 2, 2, 1);
        pane.add(getField(), 2, 2, 2, 1);
        pane.add(getLabel("Year"), 4, 2, 1, 1);
        pane.add(getField(), 5, 2, 1, 1);
        pane.add(getLabel("CVV"), 6, 2, 1, 1);
        pane.add(getField(), 7, 2, 1, 1);

        pane.getColumnConstraints().addAll(getCc(70), getCc(20), getCc(80), getCc(20), getCc(25), getCc(90), getCc(80), getCc(100));

        CheckBox gridLines = new CheckBox("Show grid lines");
        gridLines.selectedProperty().addListener((obs, old, val) -> pane.gridLinesVisibleProperty().set(val));
        root.getChildren().addAll(gridLines, pane);
    }

    private ColumnConstraints getCc(double width) {
        ColumnConstraints cc = new ColumnConstraints();
        cc.setPrefWidth(width);
        return cc;
    }

    private Label getLabel(String txt) {
        Label lbl = new Label(txt);
        lbl.setMinWidth(Region.USE_PREF_SIZE);
        return lbl;
    }

    private TextField getField() {
        TextField field = new TextField();
        field.setMaxWidth(Double.MAX_VALUE);
        return field;
    }
}
Run Code Online (Sandbox Code Playgroud)