GridPane
是JavaFX 2.0中功能最強大,最靈活的布局窗格。 它在由行和列組成的靈活網格中布置其子項,與Swing的
GridBagLayout
或HTML的表格模型非常相似。 這種方法使該窗格非常適合于任何形式的表單(例如網站上的聯系表單)。 您有能力...
- 將任何
Node
應用于GridPane
的單元格(由列和行指定) - 讓
Node
跨越多個列/行 - 使
Node
在其所應用于的單元格中對齊 - 為
Node
設置水平或垂直增長 - 并保留要保留在單元中
Node
周圍的邊距。

GridPane
的靈活性也擴展到了非常靈活的API。 您可以使用諸如setColumnIndex(node, index)
或setRowSpan(node, value)
類的靜態類方法,也可以使用諸如gridpane.add(node, column, row, columnSpan, rowSpan)
類的便捷實例方法。
注意:
- 您
GridPane
的最大列數或行數,因為它會自動增長。 - 一列的大小由該列中最寬的
Node
自動確定,每行的高度由該行中的最高Node
確定。
最后一點可能是有關GridPane
的最重要的事實,因為必須考慮每個單個Node
的列/行和列跨度/行跨度,才能獲得所需的布局。
對于更復雜的布局,最好在一張紙上繪制布局,并為列和行繪制所有線條。 這將簡化開發,因為您可以直接查看每個Node
必須放置在哪個單元格中以及它們必須跨越多少行或列。
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;/*** Created on: 23.06.2012* @author Sebastian Damm*/
public class GridPaneExample extends Application
{@Overridepublic void start(Stage primaryStage) throws Exception{GridPane gridPane = new GridPane();gridPane.setPadding(new Insets(40, 0, 0, 50));gridPane.setHgap(5); gridPane.setVgap(5);Scene scene = new Scene(gridPane, 300, 150);Label lbUser = new Label('Username:');GridPane.setHalignment(lbUser, HPos.RIGHT);TextField tfUser = new TextField();Label lbPass = new Label('Password:');GridPane.setHalignment(lbPass, HPos.RIGHT);PasswordField tfPass = new PasswordField();Button btLogin = new Button('Login');GridPane.setMargin(btLogin, new Insets(10, 0, 0, 0));gridPane.add(lbUser, 0, 0);gridPane.add(tfUser, 1, 0);gridPane.add(lbPass, 0, 1);gridPane.add(tfPass, 1, 1);gridPane.add(btLogin, 1, 2);primaryStage.setTitle('GridPaneExample 1');primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args){ Application.launch(args); }
}
在這里,您可以看到一個小的登錄表單,其中包含兩個標簽和兩個用于用戶名和密碼的文本字段。 此外,還有一個“登錄”按鈕。
在第21-23行中,我們創建GridPane
并應用一些填充。 此外,您可以指定每個Node
之間要保留的水平和垂直間隙。 接下來,看一下第28行:可以使用靜態類方法GridPane.setHalignment(Node node, HPos pos)
分別設置GridPane.setValignment(Node node, VPos pos)
GridPane.setHalignment(Node node, HPos pos)
來設置Node
在其放入的單元格邊界內的對齊方式。 GridPane.setValignment(Node node, VPos pos)
。 在第36行中,您可以看到如何通過使用GridPane.setMargin(Node node, Insets insets)
方法在單個Node
周圍放置單個邊距。 最后,在線路38至42,我們每個添加Node
到GridPane
并指定列和排Node
。
您的應用程序現在應如下所示:

在下一個示例中,您將看到為什么我們需要在更復雜的布局中設置每個Node
的列跨度和行跨度。 看一下這段代碼:
GridPane –示例2:用戶表單
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.paint.RadialGradientBuilder;
import javafx.scene.paint.Stop;
import javafx.stage.Stage;/*** Created on: 23.06.2012* @author Sebastian Damm*/
public class GridPaneExample2 extends Application
{private final Paint background = RadialGradientBuilder.create().stops(new Stop(0d, Color.TURQUOISE), new Stop(1, Color.web('3A5998'))).centerX(0.5d).centerY(0.5d).build();private final String LABEL_STYLE = '-fx-text-fill: white; -fx-font-size: 14;'+ '-fx-effect: dropshadow(one-pass-box, black, 5, 0, 1, 1);';@Overridepublic void start(Stage primaryStage) throws Exception{Scene scene = new Scene(createGridPane(), 370, 250, background);primaryStage.setTitle('GridPaneExample 2 - User form');primaryStage.setScene(scene);primaryStage.show();}private GridPane createGridPane(){GridPane gridPane = new GridPane();gridPane.setPadding(new Insets(20, 0, 20, 20));gridPane.setHgap(7); gridPane.setVgap(7);Label lbFirstName = new Label('First Name:');lbFirstName.setStyle(LABEL_STYLE);GridPane.setHalignment(lbFirstName, HPos.RIGHT);TextField tfFirstName = new TextField();Label lbLastName = new Label('Last Name:');lbLastName.setStyle(LABEL_STYLE);GridPane.setHalignment(lbLastName, HPos.RIGHT);TextField tfLastName = new TextField();Label lbCity = new Label('City:');lbCity.setStyle(LABEL_STYLE);GridPane.setHalignment(lbCity, HPos.RIGHT);TextField tfCity = new TextField();Label lbStreetNr = new Label('Street/Nr.:');lbStreetNr.setStyle(LABEL_STYLE);GridPane.setHalignment(lbStreetNr, HPos.RIGHT);TextField tfStreet = new TextField();tfStreet.setPrefColumnCount(14);GridPane.setColumnSpan(tfStreet, 2);TextField tfNumber = new TextField();tfNumber.setPrefColumnCount(3);Label lbNotes = new Label('Notes:');lbNotes.setStyle(LABEL_STYLE);GridPane.setHalignment(lbNotes, HPos.RIGHT);TextArea taNotes = new TextArea();taNotes.setPrefColumnCount(5);taNotes.setPrefRowCount(5);GridPane.setColumnSpan(taNotes, 3);GridPane.setRowSpan(taNotes, 2); ImageView imageView = new ImageView(new Image(getClass().getResourceAsStream('person.png'), 0, 65, true, true));GridPane.setHalignment(imageView, HPos.LEFT);GridPane.setColumnSpan(imageView, 2);GridPane.setRowSpan(imageView, 3);// gridPane.setGridLinesVisible(true);gridPane.add(lbFirstName, 0, 0); gridPane.add(tfFirstName, 1, 0);gridPane.add(imageView, 2, 0); gridPane.add(lbLastName, 0, 1);gridPane.add(tfLastName, 1, 1); gridPane.add(lbCity, 0, 2);gridPane.add(tfCity, 1, 2); gridPane.add(lbStreetNr, 0, 3);gridPane.add(tfStreet, 1, 3); gridPane.add(tfNumber, 3, 3);gridPane.add(lbNotes, 0, 4); gridPane.add(taNotes, 1, 4);return gridPane;}public static void main(String[] args){ Application.launch(args); }
}
在此示例中,我們創建具有不同輸入和圖像的用戶表單。 為了使應用程序看起來更好,我為Scene
的背景創建了RadialGradient
,并為每個標簽應用了白色字體顏色和一些陰影。
該應用程序應如下所示:

與前面的示例相比,第一個差異發生在第64行。
使用GridPane.setColumnSpan(tfStreet, 2);
我告訴這個TextField
占據兩列。 這是必需的,因為我希望此文本字段比其他文本字段寬一點(請參見第63行)。 否則,第二列將與該文本字段一樣寬,因此將較小的文本字段拉伸。 TextArea
(從第71行開始)和ImageView
(從77行開始)跨越多個列和行。 接下來,看一下第83行。如果刪除注釋行并啟動應用程序,則它應如下所示:

如您所見,此方法使所有網格線(包括每個Node
之間的水平和垂直間隙)可見,如果您的Nodes
沒有按照您希望的方式對齊,這將是一個很大的幫助。
我不知道在學習Swing和GridBagLayout
過程中我希望有多少次這樣的方法,我敢打賭我不是唯一的一個;)
最后,請刪除所有指定了列跨度或行跨度的行(第64、74、75、80、81行)。 這將幫助您了解列跨度和行跨度的必要性。


您會看到,每個Node
占用一個單元格,并且布局非常混亂,因為每列/行的寬度/高度取決于最寬/最高的子Node
。
GridPane –示例3:setConstraints方法
實例方法add
'提供了兩種版本,一種具有Node
,列和行,一種具有附加的列跨度和行跨度。 如前兩個示例中一樣,必須使用專用的類方法(例如GridPane.setHalignment
來設置其他屬性(如對齊或增長)。
但是還有另一種不錯的方法: GridPane.setConstraints(...)
方法。 目前(JavaFX 2.2) setConstraints(Node child, int columnIndex, int rowIndex)
有五個此方法的重載版本setConstraints(Node child, int columnIndex, int rowIndex)
設置setConstraints(Node child, int columnIndex, int rowIndex, int columnspan, int rowspan, HPos halignment, VPos valignment, Priority hgrow, Priority vgrow, Insets margin)
。
這與Swing的GridBagConstraints
非常相似,但是在這里您不必創建專用對象并將其重用于多個圖形對象。
如果將約束應用于這樣的每個Node
,則只需將Nodes
添加到GridPane′s
的子GridPane′s
集合中即可。
使用這種方法,第二個示例的代碼如下所示:
private GridPane createGrid(){GridPane gridPane = new GridPane();gridPane.setPadding(new Insets(20, 0, 20, 20));gridPane.setHgap(7); gridPane.setVgap(7);Label lbFirstName = new Label('First Name:');lbFirstName.setStyle(LABEL_STYLE);GridPane.setConstraints(lbFirstName, 0, 0, 1, 1, HPos.RIGHT, VPos.CENTER);TextField tfFirstName = new TextField();GridPane.setConstraints(tfFirstName, 1, 0);Label lbLastName = new Label('Last Name:');lbLastName.setStyle(LABEL_STYLE);GridPane.setConstraints(lbLastName, 0, 1, 1, 1, HPos.RIGHT, VPos.CENTER);TextField tfLastName = new TextField();GridPane.setConstraints(tfLastName, 1, 1);Label lbCity = new Label('City:');lbCity.setStyle(LABEL_STYLE);GridPane.setConstraints(lbCity, 0, 2, 1, 1, HPos.RIGHT, VPos.CENTER);TextField tfCity = new TextField();GridPane.setConstraints(tfCity, 1, 2);Label lbStreetNr = new Label('Street/Nr.:');lbStreetNr.setStyle(LABEL_STYLE);GridPane.setConstraints(lbStreetNr, 0, 3, 1, 1, HPos.RIGHT, VPos.CENTER);TextField tfStreet = new TextField();tfStreet.setPrefColumnCount(14);GridPane.setConstraints(tfStreet, 1, 3, 2, 1);TextField tfNumber = new TextField();tfNumber.setPrefColumnCount(3);GridPane.setConstraints(tfNumber, 3, 3);Label lbNotes = new Label('Notes:');lbNotes.setStyle(LABEL_STYLE);GridPane.setConstraints(lbNotes, 0, 4, 1, 1, HPos.RIGHT, VPos.CENTER);TextArea taNotes = new TextArea();taNotes.setPrefColumnCount(5);taNotes.setPrefRowCount(5);GridPane.setConstraints(taNotes, 1, 4, 3, 2);ImageView imageView = new ImageView(new Image(getClass().getResourceAsStream('person.png'), 0, 65, true, true));GridPane.setConstraints(imageView, 2, 0, 3, 3, HPos.LEFT, VPos.CENTER);gridPane.getChildren().addAll(lbFirstName, tfFirstName, imageView, lbLastName, tfLastName, lbCity, tfCity, lbStreetNr, tfStreet, tfNumber, lbNotes, taNotes);return gridPane;}
您可以在第51-53行看到重載的setConstraints(...)
方法的用法,以及如何將Nodes
簡單地添加到GridPane
。
我希望我能對JavaFX 2.0中的GridPane
進行很好的介紹。 隨時添加評論和發表問題。
參考: JavaFX 2.0布局窗格–來自我們JCG合作伙伴 Sebastian Damm的GridPane ,在Java博客上的Just my 2 cents上。
翻譯自: https://www.javacodegeeks.com/2012/07/javafx-20-layout-panes-gridpane.html