Javafx Layout Panes
Javafx Layout Panes
This lecture of the JavaFX tutorial covers layout management of nodes. We mention
these layout panes: FlowPane, HBox, BorderPane, AnchorPane, GridPane, and MigPane. In
addition, we show how to position nodes in absolute coordinates with the Pane.
Layout panes are containers which are used for flexible and dynamic arrangements
of UI controls within a scene graph of a JavaFX application. As a window is resized,
the layout pane automatically repositions and resizes the nodes it contains.
FlowPane – lays out its children in a flow that wraps at the flowpane's
boundary.
HBox – arranges its content nodes horizontally in a single row.
AnchorPane – anchor nodes to the top, bottom, left side, or center of the pane.
BorderPane – lays out its content nodes in the top, bottom, right, left, or center
region.
StackPane – places its content nodes in a back-to-front single stack.
TilePane – places its content nodes in uniformly sized layout cells or tiles.
Absolute layout
The Pane node can be used to position nodes in absolute coordinates. Complex
layouts should be always created using layout managers; absolute layout is used in
specific situations (for instance, positioning charts or images).
AbsoluteLayoutEx.java
package com.ead.uos;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
/**
* E.A.D JavaFX tutorial
*
* This program positions three shapes
* using absolute coordinates.
*
* Last modified: June 2020
*/
@Override
public void start(Stage stage) {
initUI(stage);
}
stage.setTitle("Absolute layout");
stage.setScene(scene);
stage.show();
}
This examples shows three shapes: a rectangle, a line, and a circle. The shapes are
positioned using absolute coordinates.
The Line and Circle shapes take absolute coordinate values in their constructors. The
colour of the line is changed with the setStroke() method, and the colour of the circle
interior is changed with the setFill() method.
FlowPane
FlowPane positions nodes in a row or a column, where the nodes are wrapped when
they all cannot be shown. The default orientation of a flow pane is
horizontal. FlowPane has a very limited usage.
FlowPaneEx.java
package com.ead.uos;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
/**
* E.A.D JavaFx Tutorial
*
* This program uses a FlowPane to position
* twenty buttons.
*
* Last modified: June 2020
*/
@Override
public void start(Stage stage) {
initUI(stage);
}
stage.setTitle("FlowPane");
stage.setScene(scene);
stage.show();
}
In the example, we place twenty buttons in the FlowPane. The buttons are wrapped
into other row(s) if they cannot be shown all in a single row.
A horizontal FlowPane is created. The second and third parameters specify the
horizontal and the vertical gap between nodes in the pane.
root.setPadding(new Insets(5));
Twenty buttons are added to the flow pane. The buttons show integer values.
Figure: FlowPane
HBox
HBox lays out its children in a single horizontal row. This pane is used in cooperation
with other layout managers to create layouts. It is suited for doing basic layouts.
RowOfButtonsEx.java
package com.ead.uos;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
/**
* E.A.D JavaFx Tutorial
*
* This program shows four buttons in
* a right-aligned, horizontal row with a HBox.
*
* Last modified: June 2020
*/
@Override
public void start(Stage stage) {
initUI(stage);
}
The example shows four buttons in a single row. The row is right-aligned. There is
some space between the buttons.
root.setPadding(new Insets(10));
root.setAlignment(Pos.BASELINE_RIGHT);
BorderPane
BorderPane lays out children in top, left, right, bottom, and center positions. It can be
used to create the classic looking application layouts.
BorderPaneEx.java
package com.ead.uos;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
/**
* E.A.D JavaFx Tutorial
*
* This program places five labels into
* the BorderPane's five areas.
*
* Last modified: June 2020
*/
setAlignment(Pos.BASELINE_CENTER);
}
}
@Override
public void start(Stage stage) {
initUI(stage);
}
root.setTop(getTopLabel());
root.setBottom(getBottomLabel());
root.setLeft(getLeftLabel());
root.setRight(getRightLabel());
root.setCenter(getCenterLabel());
stage.setTitle("BorderPane");
stage.setScene(scene);
stage.show();
}
return lbl;
}
return lbl;
}
return lbl;
}
return lbl;
}
return lbl;
}
The nodes are positioned using the setTop(), setBottom(), setLeft(), setRight(),
and setCenter() methods.
lbl.prefWidthProperty().bind(root.widthProperty());
BorderPane honours the preferred size of its children. In case of a label, it is a size big
enough to show its text. We bind the preferred width property of the label to the
corresponding property of the pane. This way the label is enlarged from the left to the
right of the pane.
We change the style of the label in order to see its boundaries clearly.
Figure: BorderPane
AnchorPane
AnchorPane anchors the edges of child nodes to an offset from the anchor pane's
edges. If the anchor pane has a border or padding set, the offsets will be measured
from the inside edge of those insets. AnchorPane is a simple layout pane which must be
used with other layout panes to create meaningful layouts.
CornerButtonsEx.java
package com.ead.uos;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
/**
* E.A.D JavaFx Tutorial
*
* This program shows two buttons in the
* bottom-right corner of the window. It uses
* an AnchorPane and an HBox.
*
* Last modified: June 2020
*/
@Override
public void start(Stage stage) {
initUI(stage);
}
root.getChildren().addAll(hbox);
AnchorPane.setRightAnchor(hbox, 10d);
AnchorPane.setBottomAnchor(hbox, 10d);
stage.setTitle("Corner buttons");
stage.setScene(scene);
stage.show();
}
The example uses an AnchorPane and a HBox to position two buttons into the bottom-
right corner of the window.
The two buttons are placed in a HBox. We use a constructor where we directly put the
button objects.
root.getChildren().addAll(hbox);
AnchorPane.setRightAnchor(hbox, 10d);
The setRightAnchor() method anchors the hbox to the right edge of the pane. The
second parameters gives some offset from the edge.
AnchorPane.setBottomAnchor(hbox, 10d);
The setBottomAnchor() method anchors the hbox to the bottom edge of the pane.
GridPane
GridPane places its nodes into a grid of rows and columns. Nodes may span multiple
rows or columns. GridPane is the most flexible built-in layout pane.
The setGridLinesVisible() enables to show the lines of the layout grid, which allows
us to visually debug the layout.
NewFolderEx.java
package com.ead.uos;
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.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.stage.Stage;
/**
* E.A.D JavaFx Tutorial
*
* This program creates a NewFolder layout with
* a GridPane.
*
* Last modified: June 2020
*/
@Override
public void start(Stage stage) {
initUI(stage);
}
root.getColumnConstraints().addAll(cons1, cons2);
root.getRowConstraints().addAll(rcons1, rcons2);
GridPane.setHalignment(okBtn, HPos.RIGHT);
root.add(lbl, 0, 0);
root.add(field, 1, 0, 3, 1);
root.add(view, 0, 1, 4, 2);
root.add(okBtn, 2, 3);
root.add(closeBtn, 3, 3);
stage.setTitle("New folder");
stage.setScene(scene);
stage.show();
}
The layout of this example consists of a label, text field, list view, and two buttons.
root.setHgap(8);
root.setVgap(8);
These two methods create horizontal and vertical gaps between the nodes.
root.getColumnConstraints().addAll(cons1, cons2);
In the layout, we need to make the second column growable. By default, the grid
pane shows its children in their preferred sizes and does not enlarge them when the
window is enlarged. We create column constraints, where we set the horizontal grow
priority to Priority.ALWAYS for the second column. (There is not a specific method to
do this.) In the end, this makes the text field and the list view controls grow in the
horizontal direction as the window is enlarged.
root.getRowConstraints().addAll(rcons1, rcons2);
In a similar fashion, we make the second row growable. By making the second
column and row growable, the list view grows in both directions, taking the bulk of
the client area.
GridPane.setHalignment(okBtn, HPos.RIGHT);
root.add(lbl, 0, 0);
The label control is added to the grid. The first two parameters of the add() method
are the column and the row index. The indexes start from zero.
root.add(field, 1, 0, 3, 1);
The overloaded add() method specifies also the column and row span. The text field
goes to the second column and first row. It spans three columns and one row.
Figure: New folder
MigPane
MigPane is a very powerful third-party layout manager. It uses
the MigLayout manager, which is available for Swing, SWT, and JavaFX. It is highly
recommended to consider this manager.
To use the MigPane, it is necessary to include the JARs to the project libraries. The
JARs for sources and javadoc are optional.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
import org.tbee.javafx.scene.layout.MigPane;
/**
* E.A.D JavaFx Tutorial
*
* This program creates a Windows layout with
* a MigPane.
*
* Last modified: June 2020
*/
MigPane root;
@Override
public void start(Stage stage) {
initUI(stage);
}
stage.setTitle("Windows");
stage.setScene(scene);
stage.show();
}
root.add(arg[0], "wrap");
root.add(arg[1], "w 200, h 200, span 2 2, grow");
root.add(arg[2], "wrap");
root.add(arg[3], "top, wrap");
root.add(arg[4]);
root.add(arg[5], "skip");
}
public static void main(String[] args) {
launch(args);
}
}
The example uses six controls, four buttons, a label, and a list view.
The three strings of the MigPane constructor specify the general, column, and row
constraints. The [grow][] constraint specifies that there are two columns and the first
one is growable. Likewise, the [][][grow][] constraint tells the MigPane that there are
four rows and the third one is growable. If we put the debug constraint into the
general constraints, we can visually debug the layout.
root.add(arg[0], "wrap");
The label control goes into the first row and first column. It is possible (but not
necessary) to explicitly specify the cell indexes. The wrap constraint starts a new row.
The w and h constrains specify the initial width and height of the list view control. It is
a best practice that only the layout manager sets the size of its components. In other
words, calling methods line setMinSize() directly on controls is a poor practice.
The span constraint makes the control span two columns and two rows. Finally,
the grow constraint makes the control grow in both directions when the window is
resized.
root.add(arg[2], "wrap");
The third control is the Activate button. It goes next to the list view. After placing this
control, we start a new row.
The Close button goes next to the list view and below the Activate button.
The top constraint aligns the button to the top of its cell.
root.add(arg[4]);
We made the list view span two rows. After placing the previous buttons into two
separate rows, the next button goes automatically below the list view.
root.add(arg[5], "skip");
The last button skips one column. So it is placed in the third column and fourth row.
Figure: Windows layout created with a MigPane