The
GridPane
is without a doubt the most powerfull and flexible layout pane in JavaFX 2.0.It lays out its children in a flexible grid of columns and rows and is very similar to Swing´s
GridBagLayout
or HTML´s table model. This approach makes this pane very well suited for any kind of form (like contact forms on a website).You have the ability to...
-
apply any
Node
to a cell (specified by column and row) in theGridPane
-
to let the
Node
span multiple columns/rows -
to align the
Node
in the cell it was applied to -
to set horizontal or vertical grow for the
Node
-
and to apply a margin to be kept around the
Node
in the cell.
GridPane
also extends to a very flexible API. You can use static class methods like setColumnIndex(node, index)
or setRowSpan(node, value)
, or you can use convenience instance methods like gridpane.add(node, column, row, columnSpan, rowSpan)
.Note:
-
You don´t have to set the maximum number of columns or rows in the
GridPane
as it will grow automatically. -
The size of one column is automatically determined by the widest
Node
in this column, the height of each row is determined by the tallestNode
in the row.
GridPane
as it has to be considered for the column/row and the column span/row span of every single Node
in order to get the layout you want.For more complex layouts it is a very good idea to draw the layout on a piece of paper and to draw all lines for the columns and rows. This will ease development because you can diretly see in which cell you have to put each
Node
and how many rows or columns they have to span.Lets have a look at the first simple example:
GridPane – Example 1
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 { @Override public 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); } }
Here you can see a little login form with with two labels and two textfields for the username and the password. Additionally theres a 'login' button.
In lines 21-23 we create the
GridPane
and apply some padding. Furthermore you can specify a horizontal and a vertical gap to be kept between each Node
. Next, take a look at line 28: The alignment of a Node
inside the boundaries of the cell it was put into, can be set with the static class methods GridPane.setHalignment(Node node, HPos pos)
, respectively GridPane.setValignment(Node node, VPos pos)
.In line 36 you can see how to put a individual margin around a single
Node
by using the GridPane.setMargin(Node node, Insets insets)
method.Finally in lines 38 to 42 we add each
Node
to the GridPane
and specify the column and the row of the Node
.Your application should look like this now:
In the next example you will see, why we need to set the column span and the row span of each
Node
in more complex layouts. Have a look at this code:GridPane – Example 2: User form
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);"; @Override public 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); } }
In this example we create a user form with different inputs and an image. To make the application appear a little nicer, i created a
RadialGradient
for the background of the Scene
and applied a white font color and a little dropshadow to each label.The application should look like this:
Compared to the previous example, the first difference occurs in line 64.
With
GridPane.setColumnSpan(tfStreet, 2);
i tell this TextField
to occupy two columns. This is needed, because i want this textfield to be a little wider (see line 63) than the other textfields. Otherwise the second column would be as wide as this textfield and therefore stretch the smaller ones.The
TextArea
(starting at line 71) and the ImageView
(line 77) span across multiple columns and rows.
Next, take a look at line 83. If you remove the comment lines and start the application, it should look like this:
As you can see, this method makes all grid lines (including the horizontal and vertical gap between each
Node
visible which can be a great help if your Nodes
arent aligned the way you want it.I don´t know how many times i wished for a method like this during the time i learned Swing and the
GridBagLayout
and i bet that i´m not the only one ;)Finally, please remove all lines, where column span or row span are specified (lines 64, 74, 75, 80, 81). This will help you to understand the necessity of column span and row span.
You can see, that each Node
occupies one single cell and that the layout is pretty messed up because the width/height of each column/row depend on the widest/tallest child Node
.
GridPane – Example 3: The setConstraints method
The instance method add
"only" provides two versions, one with the Node
, the column and the row, and one with additional column span and row span. Other properties like the alignment or the grow have to be set with dedicated class methods like GridPane.setHalignment
like in the first two examples.
But theres another nice way: the GridPane.setConstraints(...)
method.
setConstraints(Node child, int columnIndex, int rowIndex)
to
setConstraints(Node child, int columnIndex, int rowIndex, int columnspan, int rowspan, HPos halignment, VPos valignment, Priority hgrow, Priority vgrow, Insets margin)
.
This is pretty similiar to Swing´s GridBagConstraints
but here you don´t have to create a dedicated object and reuse it for multiple graphical objects.
If you apply the constraints to every Node
like this, you can simply add the Nodes
to the GridPane´s
collections of children.
With this approach the code of the second example looks like this:
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; }
You can see the usage of the overloaded setConstraints(...)
methods and how you can simply add the Nodes
to the GridPane
in lines 51-53.
I hope i could provide a good introduction to the GridPane
in JavaFX 2.0. Feel free to add comments and post questions.
Nicely explained !! :)
ReplyDeletevery nice & easy to understand !!:)
Deletegood man!
ReplyDeletethis app run in browser ok?
good tutorial. thumbs Up
ReplyDeleteluving ur tutorials.. waiting for more topics
ReplyDeletegood tutorial
ReplyDeleteA very good and practical example of GridPane.
ReplyDeletegood and easy stuff
ReplyDeletehey friends please tell me about javafx in briefly because i don't know what we can do using javafx like desktop application or web application so please please tell me my e-mail :jaygori143@gmail.com
ReplyDeletehttp://www.javafxapps.in/tutorial/Getting-started-with-your-first-JavaFX-Application.html
Deleteas I can put an image on a background gridpane?
ReplyDeleteAlveo
ReplyDeleteIncredible! This blog looks just like my old
one! It's on a completely different subject but it
has pretty much the same page layout and design. Outstanding choice of colors!
This comment has been removed by a blog administrator.
ReplyDeleteKommt da noch was Herr Damm :-D Grüße aus Miltenberg
ReplyDeleteThank you veryy much From Algeria :D.
ReplyDeleteESI-Algiers
No offense meant to the author...But in working with JavaFX and JavaFXML it is apparent to me that the tools and the framework, while there, are extremely obtuse and they themselves present the challenge to making this easy to put together. I supposed when microsoft invented..perhaps perfected this environment originally, in the early 1990's (aka visual basic) and then again with WPF in the early 2000's it has ruined me to working with Java really ever again. Man you can build a house with a hammer and a nail, but personally I prefer using power tools. And folks, these do not qualify as power tools by any stretch of the imagination. I recommend highly, unless your organization requires it, to leave this crapola behind and use visual studio and it's variety of frameworks to do development.
ReplyDeleteCool and I have a dandy offer: What House Renovations Can You Claim On Tax residential renovation contractors near me
ReplyDelete