Layout Panes

As we've seen before, layout panes are JavaFX's way of organizing the various GUI elements of your application inside the window. For example, we've used HBox to arrange elements beside each other, and BorderPane to organize elements in specific areas of the window. We will be focusing on four layout panes:

Pane Use
BorderPane Used to place elements in regions of the window, Top/Left/Center/Right/Bottom
FlowPane Used to place elements next to each other until it runs out of room, then wraps around. Imagine text in Word or Pages wrapping at the end of a line.
HBox Used to arrange elements in rows
VBox Used to arrange elements in columns

We'll look at each of these panes individually, but there are a few aspects of layout panes we need to examine first.


The javafx.geometry.Pos enumeration

Pos allows us to set the alignment of Nodes within HBoxes and VBoxes. It is an enumeration, which is an ordered set of constants. You may remember the enum declaration from C, like so:

typedef enum {
    HEARTS,
    DIAMONDS,
    CLUBS,
    SPADES
} CARD_SUIT;

Java enumerations work very much the same way:

public enum CARD_SUIT {
    HEARTS, DIAMONDS, CLUBS, SPADES
}

CARD_SUIT suit = HEARTS;

They provide an easy interface to define types that are useful for categorization (like the suit of a playing card), but don't really need any data or methods defined on them. Additionally, they can be used to programmatically define a set of options, both those selected by a user or used only internally. Pos defines various alignments within a layout pane, which fits both definitions!

Constant V Alignment H Alignment
Pos.TOP_LEFT Top Left
Pos.TOP_CENTER Top Center
Pos.TOP_RIGHT Top Right
Pos.CENTER_LEFT Center Left
Pos.CENTER Center Center
Pos.CENTER_RIGHT Center Right
Pos.BOTTOM_LEFT Bottom Left
Pos.BOTTOM_CENTER Bottom Center
Pos.BOTTOM_RIGHT Bottom Right
Pos.BASELINE_LEFT Baseline Left
Pos.BASELINE_CENTER Baseline Center
Pos.BASELINE_RIGHT Baseline Right
javafx.geometry.Insets

Let's see what this code produces:

import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;

public class BadDesign extends Application
{
    private static void main(String[] args) 
    {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage)
    {
        // Making three buttons
        Button btn1 = new Button();
        btn1.setText("Button 1");
        Button btn2 = new Button();
        btn2.setText("Button 2");
        Button btn3 = new Button();
        btn3.setText("Button 3");

        // We want an HBox with 10 pixels between the buttons!
        // It will look great!
        HBox hbox = new HBox(10, btn1, btn2, btn3);

        Scene scene = new Scene(hbox);

        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

Bad UI Design

It's alright, but really want we want in addition is 10px of spacing around the entirety of each button. To do so, we can use the Insets class to set the padding of the layout pane, or the spacing between the edges of the pane (in this case an HBox), and the elements inside.

We can create Insets in two ways:

// For uniform padding
hbox.setPadding(new Insets(10));

// To set the padding for each edge
// The order is Top/Right/Bottom/Left. To remember this, I use the mnemonic:
// TRouBLe
hbox.setPadding(new Insets(20, 10, 20, 10));

If we update our code from before:

import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.geometry.*;

public class BetterDesign extends Application
{
    private static void main(String[] args) 
    {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage)
    {
        // Making three buttons
        Button btn1 = new Button();
        btn1.setText("Button 1");
        Button btn2 = new Button();
        btn2.setText("Button 2");
        Button btn3 = new Button();
        btn3.setText("Button 3");

        // We want an HBox with 10 pixels between the buttons!
        // It will look great!
        HBox hbox = new HBox(10, btn1, btn2, btn3);
        hbox.setPadding(new Insets(10));

        Scene scene = new Scene(hbox);

        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

Better UI Design

That's looking better! If we wanted, we could also use Insets to set a margin around an individual element, like this:

hbox.setMargin(btn1, new Insets(10));
javafx.scene.control.Region and javafx.scene.layout.Priority

Region allows us to create empty spaces in our application between elements. Let's say we wanted an application with three buttons, but we wanted two on the left side of the window, and the third on the right. By placing a Region element between the second and third buttons, and configuring it to grow to fill extra space, we can in essence model this behavior.

The Priority enumeration is used to configure a node to grow to fill available space, either with HBox's setHgrow() or VBox's setVgrow() methods. By default, elements are configured to Priority.NEVER, or never to grow to fill available space. There are two more options used:

Constant Description
Priority.ALWAYS Always grow to fill available space
Priority.SOMETIMES Grow to fill available space in the absence of a element using Priority.ALWAYS
import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.geometry.*;

public class FloatingButtons extends Application
{
    public static void main(String[] args)
    {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage)
    {
        // Create the buttons
        Button btn1 = new Button();
        btn1.setText("Button 1");
        Button btn2 = new Button();
        btn2.setText("Button 2");
        Button btn3 = new Button();
        btn3.setText("Button 3");

        // Create the spacer
        Region spcr = new Region();

        // Create the layout pane
        HBox hbox = new HBox(10, btn1, btn2, spcr, btn3);

        // Set margins around the buttons, since we only want extra space 
        // around them, not the spacer
        hbox.setMargin(btn1, new Insets(10));
        hbox.setMargin(btn2, new Insets(10));
        hbox.setMargin(btn3, new Insets(10));

        // Set the spacer to always grow horizontally.
        hbox.setHgrow(spcr, Priority.ALWAYS);

        Scene scene = new Scene(hbox);

        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

Floating Buttons 1

Floating Buttons 2


BorderPane
Method Description
BorderPane() Creates an empty pane
BorderPane(Node) Creates a pane with a Node at the center
BorderPane(Node, Node, Node, Node, Node) Creates a pane with Nodes in the following order: Center/Top/Right/Bottom/Left
void setCenter(Node) Sets the center Node
void setTop(Node) Sets the top Node
void setRight(Node) Sets the right Node
void setBottom(Node) Sets the bottom Node
void setLeft(Node) Sets the left Node
void setAlignment(Pos) Sets the alignment of Node elements
static void setMargin(Node, Insets) Sets the margin of the specified child Node
import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.geometry.*;

public class BorderPaneExample extends Application
{
    // We'll show where all of the panes show up.
    private static Button topBtn;
    private static Button leftBtn;
    private static Button ctrBtn;
    private static Button rightBtn;
    private static Button btmBtn;

    public static void main(String[] args)
    {
        launch(args);
    }
    
    @Override
    public void start(Stage primaryStage)
    {
        topBtn = new Button("Top Button");
        leftBtn = new Button("Left Button");
        ctrBtn = new Button("Center Button");
        rightBtn = new Button("Right Button");
        btmBtn = new Button("Bottom Button");

        BorderPane pane = new BorderPane(ctrBtn, topBtn, rightBtn, btmBtn, leftBtn);
        Scene scene = new Scene(pane);

        primaryStage.setScene(scene);
        primaryStage.setTitle("BorderPane Example");
        primaryStage.show();
    }
}

BorderPane Example


javafx.scene.layout.FlowPane

FlowPanes, whether in their horizontal or vertical flavors, arrange elements beside each other in a row or column until a specified width/height, then wraps around to the next row/column.

Method Description
FlowPane() Creates an empty FlowPane with 0 for the horizontal and vertical gap
FlowPane(double, double) Creates an empty FlowPane with a specified h- and v-gap
FlowPane(double, double, Node...) Creates a FlowPane with a specified h- and v-gap and children
FlowPane(Node...) Creates a FlowPane with specified children and 0 for the h- and v-gap
FlowPane(Orientation) Creates a FlowPane with the specified orientation (Orientation.VERTICAL or .HORIZONTAL) and 0 for the h- and v-gaps
FlowPane(Orientation, double, double) Creates a FlowPane with the specified orientation, h-, and v-gaps
FlowPane(Orientation, double, double, Node...) Creates a FlowPane with the specified orientation, h-gap, v-gap, and children
FlowPane(Orientation, Node...) Creates a FlowPane with the specified orientation and children
ObservableList<Node> getChildren() Gets the children of the pane
void setAlignment(Pos) Sets the alignment of the child nodes
void setColumnAlignment(Pos) Sets the column (vertical) alignment of the child nodes
void setHgap(double) Sets the horizontal gap
void setOrientation(Orientation) Sets the orientation
void setRowAlignment(Pos) Sets the row (horizontal) alignment of the child nodes
void setVgap(double) Sets the vertical gap

FlowPane Example


javafx.scene.layout.HBox

HBoxes arrange elements horizontally next to each other. Whenever you want a definite row, without wrapping, you should use an HBox.

Method Description
HBox() Creates a new, empty HBox
HBox(double) Creates a new, empty HBox with a specified spacing
HBox(Node...) Creates a new HBox with the specified children
HBox(double, Node...) Creates a new HBox with the specified children and spacing
ObservableList<Node> getChildren() Gets the children of the pane
void setAlignment(Pos) Sets the alignment of the child nodes
void setHgrow(Node, Priority) Set the growth behavior of a child node
void setMargin(Node, Insets) Set the margin of a child node
void setPadding(Insets) Sets the padding of the pane
void setSpacing(double) Sets the spacing between elements in the pane

HBox Example


javafx.scene.layout.VBox

VBoxes arrange vertically on top of each other. You should use a VBox to position elements you want in a column.

Method Description
VBox() Creates a new, empty VBox
VBox(double) Creates a new, empty VBox with a specified spacing
VBox(Node...) Creates a new VBox with the specified children
VBox(double, Node...) Creates a new VBox with the specified children and spacing
ObservableList<Node> getChildren() Gets the children of the pane
void setAlignment(Pos) Sets the alignment of the child nodes
void setVgrow(Node, Priority) Set the growth behavior of a child node
void setMargin(Node, Insets) Set the margin of a child node
void setPadding(Insets) Sets the padding of the pane
void setSpacing(double) Sets the spacing between elements in the pane

VBox Example