Every application with more than one button needs to organise its nodes in some way. JavaFX’s default layouts can achieve this with little to no effort, and with surprising flexibility. In fact, from dashboards with multiple charts, to games with terrain, characters and user controls, JavaFX’s layout classes can achieve an impressive variety of effects.

Layouts in JavaFX are containers that provide pre-built functionality to define the position, size and alignment of nodes such as charts, images and controls. JavaFX provides 9 default layout classes, including the base class Pane, which provides only for absolute positioning.

Before I start, if you just need to see how to use one type of pane, feel free to jump ahead:

How to use this resource

There are numerous tutorials on the high-level functionality of all 9 layout panes, including from Oracle itself. What I’ll try to add with this article is a more thorough summary of the quirks, and how you can avoid (or use) them to make your user interfaces responsive, but predictable. I’ve broken this tutorial down into two sections:

  • Best practice rules on using layouts.
  • Deep dive into each layout.

There are three nodes I won’t talk about in this article: ScrollPane, TabPane and SplitPane. The primary use of these panes is to allow the user to control the viewport through which to view nodes, and not to lay them out.

  • ScrollPane: allows the user to change the viewport by scrolling or panning.
  • TabPane: allows the user to view different panes by selecting a tab.
  • SplitPane: Allows the user to alter the proportion of two panes that are visible by moving a divider.

General rules on using layouts

Choosing a layout should depend on two factors:

  • The position you want your nodes to be in (layout type)
  • The way the layout will control the position, size and alignment of its children

A good guiding principle for choosing a layout is to think about the general position you want for nodes in a layout, and to select a type of layout based on that.

Once you’ve chosen your layout type, you can fine-tune your choice based on the control you need over positioning, sizing and alignment of your nodes.

1. Layout Types

The layouts can be broken down into three types: block, grid and row/column layouts.

Each group thinks about nodes in a different way. And within a block, organises the finer-tuning of node positions differently.

Block Layouts

Block layouts are the simplest, having only one set of rules that defines the layout of their children. I’ve called them ‘block’ layouts because they do not segregate nodes into areas (grid layouts) or runs (row/column layouts).

That is to say, from the perspective of the layout logic, the pane is a single block.

In the case of the StackPane, node position is controlled through setting alignment, whereas the AnchorPane uses absolute positioning.

The AnchorPane’s absolute positioning means it can control both position and size, whereas the StackPane can only control position.

Grid Layouts

Grid layouts are the most complex, and can allow for very detailed control of the position of nodes.

The TilePane class is the easiest to use, but offers the least control over the positioning of the nodes.

In the case of the BorderPane, users are granted coarse control over positioning, but are also guaranteed certain behaviour by default. This can be a good balance for default window-behaviour use cases.

The GridPane allows for significant breadth in fine control of node position, but can be difficult and complex to use.

Row and Column Layouts

Finally, row and column layouts are designed to display nodes in a specified order, either vertically or horizontally.

Each of these comes with options to control the spacing between the nodes in the series. In the case of the FlowPane, users can also control the space between rows or columns in multi-row and multi-column settings.

Within a layout type, there are usually multiple ways to layout nodes in the same way. So, once I’ve chosen the rough positions of nodes, I tend to choose layouts based on how I want each component to behave when the layout pane is resized.

2. Choose your layout based on how it controls its children

Panes are designed to control the position, size and alignment (relative position) of children in a variety of ways. These affect how it will move and resize your nodes when the pane is resized

It’s always worth bearing in mind that windows are frequently resized by users significantly smaller or larger than you might have planned.ff

PaneLayout Positions ChildrenResizes ChildrenAligns ChildrenHas sub-regionsChildren can overlap
AnchorPane
StackPane
BorderPane
GridPane(virtual)
TilePane(virtual)
FlowPane
HBox
VBox

One common issue with using layouts is trying to resize controls. If you’re having trouble getting your layout to resize a Control like a Button, take a look at the dropdown to fix it.

Once you’ve chosen a layout, you’ll want to use it… In the next section, I’ll run through how to control the size, position and alignment of nodes in each of JavaFX’s layouts.

A deep dive into each layout

The Pane class is the base class for all layouts and will not apply any layout behaviour to its children. For this reason, the Pane is useful when you need to position a node absolutely, but you don’t want any additional resizing behaviour, or alignment.

Each layout pane extends the Pane class and provides additional functionality layered on top of the core behaviour defined in the Pane. There isn’t any magic to layout panes: they achieve the layout behaviour they want by manually calculating the layoutX and layoutY properties of every child node according to a set of rules specific to the layout they’re trying to create.

In each of the sections below, I’ll go through the behaviour and how the rules can help you use these layouts as they were designed.

I’ll go through them by Type.

Block Layouts

These are incredibly useful for deciding yourself where nodes should be displayed, and are frequently useful in designing custom content areas.

AnchorPane

The AnchorPane class is a simple layout with three guiding principles:

  • The region is a single block that any node can be positioned on
  • Anchor points set on nodes are honoured, overriding any existing maximum or minimum sizes
  • Overlapping nodes are rendered from the start of the ObservableList children to the end, meaning by default most recently-added items are rendered last.
I find the AnchorPane useful animating the size of a pane while keeping it anchored to one location in a scene.

StackPane

The StackPane is a simple layout pane similar to the AnchorPane. Both panes are relatively simple layouts that support rendering of nodes that overlap each other. However, where the AnchorPane focused on absolute positioning, the StackPane focuses on alignment-based positioning of nodes.

Grid Layouts

Grid layouts are useful for giving the user a familiar experience, by creating interfaces they’ve seen before, such as windows (border panes), galleries (tile panes) and forms (grid panes).

BorderPane

The BorderPane is designed to have top and bottom regions of fixed height, and left and right regions of fixed width. The effect is to have a centre of varying size as the BorderPane changes dimensions.

GridPane

The GridPane layout provides the finest level of control for nodes in a grid layout. This includes capability to set column- and row-specific properties for alignment and sizing, in addition to node-specific row- and column-spanning behaviour.

TilePane

A TilePane calculates its layout by adding tiles (virtual regions inside which our nodes get rendered) in one dimension and then wrapping tiles into additional rows or columns. Tiles are of a consistent size throughout the pane.

Row & Column Layouts

Row and column layouts display their content in an order across a single dimension. The FlowPane wraps content that does not fit in the primary dimension by creating additional rows or columns. VBoxes and HBoxes do not.

FlowPane

The FlowPane is designed to give your layout a responsive feel, changing the length of a row or column to suit the size of the FlowPane itself. It’s great for similar-looking items that need to be shuffled around.

HBox

The HBox positions nodes horizontally from left to right. Node resizing and alignment preferences can be set, while the order of elements can be changed by altering the order of elements in the ObservableList children.

VBox

The VBox positions nodes vertically, top-to-bottom. I’ll give you the whistle-stop tour, but checkout the HBox drop-down if you want a more detailed guide to the functionality. The internal logic is identical, but horizontal rather than vertical.

Conclusions

JavaFX has 9 pre-defined containers that provide functionality to define the position, size and alignment of nodes such as charts, images and controls. JavaFX’s layouts can achieve a huge variety of functionality and positional control.

There are three basic types of layouts: grids, rows and blocks. They define the way the layout ‘thinks’ about positioning your nodes. Sketching out a container and using this to decide the sort of layout you need is usually a great way to start.

Once you’ve chosen the basic way you want your pane to look (a grid, a row or a block) I’d recommend choosing your layouts based on how they respond to being resized. Unless you’ve made them explicitly fixed-size, users will always surprise you with bugs they pick up making windows ridiculously big (or small).