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 the GridPane
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.
The flexibility of the 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 tallest Node in the row.
The last note is probably the most important fact about the 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.
An AnchorPane is similar to a BorderPane (see my previous post JavaFX 2.0 Layout Panes - BorderPane) as it also provides several areas or regions for your nodes.
In contrast to a BorderPane, an AnchorPane provides only four different regions: Left, Right, Bottom and Top (a BorderPane additionally provides a center region).
There are several more major differences between the two panes:
In an AnchorPane you can anchor multiple nodes to one area (in a BorderPane you can only set one node to each area).
In an AnchorPane you can anchor one single node to multiple areas, i.e. anchoring a Button to the left and the top of the AnchorPane, whereas in a BorderPane every node can only be applied to one area.
In an AnchorPane you can specify the offset to the anchor.
A BorderPane provides instance methods to populate each area (i.e. setCenter(Node node), setRight(Node node), ...). An AnchorPane offers static methods like AnchorPane.setTopAnchor(Node node, Double offset) that are applied directly to a Node.
In a BorderPane each child will grow and shrink with its parent depending on the area it is applied to. In an AnchorPane children will only be resized/stretched if they are anchored to opposite sides of the pane.
For example if a Button is anchored to the left and the right anchor of an AnchorPane, the Button will be stretched horizontally.
A BorderPane is very well suited to develop more complex layouts. In general the BorderPane provides five different regions: Top, Right, Bottom, Left and Center. You can set a Node to each of these areas by calling the setTop/setBottom/set… methods. This approach makes it very easy to develop “website-like” application windows where you have a menubar or toolbar at the top, a navigation on the left, some kind of footer at the bottom, your main content in the center area and possibly some additional information at the right.
It is important to know, that each of these areas resizes differently:
The top and bottom areas will resize to their children preferred height and take all space available for their width.
The left and right areas will resize to their children preferred width and take all space available for their height.
The center area takes all space available for its height and its width.
Following graphic demonstrates the behavior of a BorderPane when resizing your application window:
FlowPanes and TilePanes are nice layout panes, if you want to layout your children consecutively one after another, either horizontally or vertically. They are quite similiar to each other as both will layout their children either in columns (in case of a horizontal Flow/TilePane) and wrap at their width or in rows (in case of a vertical Flow/TilePane) and wrap at their height.
The only major difference is, that the TilePane places all children in tiles that are the same size! So the size of the greatest children is taken for the size of each individual tile in the TilePane. Therefore a TilePane is also a nice way to size and align buttons and other controls equally. (See my previous post Sizing Buttons equally inside a VBox or HBox)
When you have multiple buttons in a VBox or a HBox you often want to size and align them equally. The default preferred width of a button is computed based on its content (which includes the text as well as possible graphics) and the default preferred size of a VBox and a HBox is based on the biggest of their children.
If you want your buttons to grow with their parent you either have to raise their max size manually or to set it to the constant Double.MAX_VALUE which forces controls to grow as big as permitted by their parent.
If you want an overview on all different layout panes in JavaFX 2.0 or if you want to know yome basic facts about them, please see my previous post Layout Panes in JavaFX 2.0.
The layout panes HBox and VBox are definitely the most basic layout containers in JavaFX 2.0. As you can already tell by their name, their purpose is to layout all their children in one horizontal row (HBox) or in one vertical column (VBox). Because they´re very easy to use and very useful regarding minor layout issues, you´ll probably use them a lot. I´ll give two examples on how you can use them. As in the other examples, first of all the code and afterwards the explanations.
HBox and VBox – Example 1
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* Created on: 20.03.2012
* @author Sebastian Damm
*/
public class HBoxandVBoxExample extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
HBox hbox = new HBox(50);
hbox.setAlignment(Pos.CENTER); // default TOP_LEFT
VBox vbox1 = new VBox();
vbox1.setAlignment(Pos.BOTTOM_CENTER);
vbox1.setStyle("-fx-border-style: solid;"
+ "-fx-border-width: 1;"
+ "-fx-border-color: black");
VBox vbox2 = new VBox(10);
vbox2.setAlignment(Pos.CENTER);
vbox2.setStyle("-fx-border-style: solid;"
+ "-fx-border-width: 1;"
+ "-fx-border-color: black");
VBox vbox3 = new VBox(20);
vbox3.setAlignment(Pos.TOP_CENTER);
vbox3.setStyle("-fx-border-style: solid;"
+ "-fx-border-width: 1;"
+ "-fx-border-color: black");
for (int i = 0; i < 5; i++)
{
Button bt = new Button("Button " + (i+1));
Button bt2 = new Button("Button " + (i+1)); // unfortunately there´s no "clone" or "copy" method
Button bt3 = new Button("Button " + (i+1));
vbox1.getChildren().add(bt);
vbox2.getChildren().add(bt2);
vbox3.getChildren().add(bt3);
}
hbox.getChildren().addAll(vbox1, vbox2, vbox3);
Scene scene = new Scene(hbox, 350, 250); // the hbox is the root node
primaryStage.setTitle("HBox and VBox Example");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
}
Basically we create three different VBoxes and put them into one HBox. In both classes you can define a spacing value either directly in the constructor or via the setSpacing method.
This value will be used as the gap between the individual children in the pane.
The line HBox hbox = new HBox(50); therefore creates a HBox to hold three VBoxes with a gap of 50 pixel between each of them.
We use the setAlignment method to specify, how the individual VBoxes should arrange and layout all their childen.
With setStyle you can apply custom CSS styles to any Node. I don´t want to go into much detail yet, because I´ll cover CSS styles in JavaFX 2.0 in one of my next posts, but if you´re already familiar with CSS you´ll probably already have noticed that the JavaFX 2.0 team fortunately decided to follow the CSS standards defined by W3C (http://www.w3.org) very closely.
If you´re not familiar with CSS you just need to know that theses lines of CSS create a 1px wide black border around the component. I use them here to show you the size of the individual VBoxes.
The next few lines should be pretty ordinary for you by now: We create five buttons for each VBox, put the different VBoxes into our HBox, declare a Scene object (with the HBox as root) and show our application.
Creating a graphical user interface that looks nice and that provides a good usability is a very common task in software development. Fortunately JavaFX 2.0 offers great support in that area.
What is a layout manager and why do we need them?
Layout managers are regions or areas that follow individual rules to (re)arrange and to (re)size all their children in relation to their own size. Generally, it is also possible to specify a fixed position of your components in an application window. But how should the window know what to do when you resize your application window? Should it leave the new available space blank? Should some components “vanish” if you make the window smaller? Should it resize some components? If yes, which one and how?
These questions show, why layout managers are necessary in software development.
Facts about layout managers in JavaFX 2.0
In JavaFX 2.0 layout managers are called “panes”
Every layout pane extends the Region class
To create your own layout pane, it is highly recommended to extend Region yourself
Types of layout panes in JavaFX 2.0
HBox (lays out its children in a horizontal row)
VBox (lays out its children in a single vertical column)
Border Pane (lays out its children in five different regions: Top, Right, Bottom, Left and Center)