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