JavaFX Controls, Layouts & FXML

Layout Panes: StackPane, FlowPane & AnchorPane

18 min Lesson 5 of 12

Layout Panes: StackPane, FlowPane & AnchorPane

The previous lessons introduced HBox, VBox, BorderPane, and GridPane — layouts that arrange children along axes or in named zones. This lesson covers three more panes that solve completely different problems: StackPane layers nodes on top of each other, FlowPane wraps content like text in a paragraph, and AnchorPane pins children to its edges with pixel-precise offsets. Every real JavaFX application reaches for at least one of these.

StackPane — Layering Nodes

StackPane is the simplest compositor in JavaFX. It draws all its children occupying the same rectangle, in order: the first child is drawn at the bottom, the last child is drawn on top. The pane sizes itself to the largest child's preferred size.

The canonical use case is placing a label or icon over a background shape or image:

import javafx.application.Application; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class StackPaneDemo extends Application { @Override public void start(Stage stage) { // Layer 1 (bottom): a coloured rounded rectangle Rectangle card = new Rectangle(200, 100); card.setArcWidth(20); card.setArcHeight(20); card.setFill(Color.STEELBLUE); // Layer 2 (top): a label centred over the card Label label = new Label("Click Me"); label.setStyle("-fx-text-fill: white; -fx-font-size: 16px; -fx-font-weight: bold;"); StackPane stack = new StackPane(card, label); // card first = bottom stage.setScene(new Scene(stack, 300, 200)); stage.setTitle("StackPane Demo"); stage.show(); } }

You can override the default centre-alignment per child using StackPane.setAlignment(node, Pos.BOTTOM_RIGHT). This lets you, for example, place a small notification badge in the corner of an avatar icon while leaving the icon itself centred.

// badge pinned to bottom-right of the stack Label badge = new Label("3"); badge.setStyle("-fx-background-color: red; -fx-text-fill: white; " + "-fx-background-radius: 8; -fx-padding: 0 5 0 5;"); StackPane.setAlignment(badge, Pos.BOTTOM_RIGHT); StackPane.setMargin(badge, new javafx.geometry.Insets(0, 4, 4, 0));
StackPane and mouse events: the topmost (last-added) child captures mouse events first. If you add a transparent overlay Region as the top layer it will block clicks on children beneath it unless you call overlay.setMouseTransparent(true).

FlowPane — Wrapping Layout

FlowPane arranges children in a horizontal row (the default) and, when the row is full, wraps onto the next row — exactly like words in a paragraph. You set a preferred wrap width and the pane decides where the breaks fall at runtime.

import javafx.geometry.Insets; import javafx.geometry.Orientation; import javafx.scene.control.Button; import javafx.scene.layout.FlowPane; FlowPane flow = new FlowPane(); flow.setHgap(8); // horizontal gap between children flow.setVgap(8); // vertical gap between rows flow.setPadding(new Insets(12)); flow.setPrefWrapLength(400); // start wrapping after ~400 px for (int i = 1; i <= 12; i++) { flow.getChildren().add(new Button("Item " + i)); }

You can switch FlowPane to vertical orientation: children then fill a column and wrap to the next column when the column height is exhausted.

FlowPane verticalFlow = new FlowPane(Orientation.VERTICAL); verticalFlow.setPrefWrapLength(200); // wrap after 200 px height

A common pattern is pairing FlowPane with a ScrollPane so the user can scroll through a large, reflowing tag cloud or image gallery:

ScrollPane scroll = new ScrollPane(flow); scroll.setFitToWidth(true); // flow fills the scroll viewport width
Prefer FlowPane for tag clouds, chip groups, and toolboxes where the number of items is dynamic or unknown at design time. For a fixed grid of equal-sized cells, prefer TilePane (which enforces uniform cell sizes) or GridPane.

AnchorPane — Pixel-Precise Edge Pinning

AnchorPane is JavaFX's answer to absolute positioning — but smarter. Instead of giving each child a fixed (x, y) coordinate, you pin the child's edges to the corresponding edges of the pane. When the pane resizes, the distance to the pinned edge is preserved, so the child moves or stretches to maintain those gaps.

You set anchors with four static helper methods:

import javafx.scene.control.Button; import javafx.scene.control.TextArea; import javafx.scene.layout.AnchorPane; AnchorPane anchor = new AnchorPane(); // A toolbar button pinned to the top-right corner Button saveBtn = new Button("Save"); AnchorPane.setTopAnchor(saveBtn, 8.0); AnchorPane.setRightAnchor(saveBtn, 8.0); // A text area that fills the pane leaving a 40 px gap at the top TextArea editor = new TextArea(); AnchorPane.setTopAnchor(editor, 40.0); AnchorPane.setBottomAnchor(editor, 0.0); AnchorPane.setLeftAnchor(editor, 0.0); AnchorPane.setRightAnchor(editor, 0.0); // stretches horizontally anchor.getChildren().addAll(saveBtn, editor);

When you set both a left and a right anchor on the same child, the child's width is not fixed — it expands and contracts as the pane resizes to keep both gaps constant. The same logic applies to top + bottom anchors controlling height. This is the correct way to build a resizable editor pane in a window.

Anchors are not margins. If you only set a left anchor, the right edge of the child floats freely — it does not snap to the right side of the pane. You must set both left and right anchors to make a child stretch horizontally.

Combining Panes in Practice

Real UIs nest these panes. A typical pattern for a simple note-taking screen combines all three:

import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; import javafx.geometry.Insets; public class CombinedLayoutDemo extends Application { @Override public void start(Stage stage) { // --- Header: avatar icon via StackPane --- Circle avatar = new Circle(20, Color.CORNFLOWERBLUE); Label initials = new Label("ES"); initials.setStyle("-fx-text-fill: white; -fx-font-weight: bold;"); StackPane avatarStack = new StackPane(avatar, initials); // --- Tag row: FlowPane --- FlowPane tags = new FlowPane(); tags.setHgap(6); tags.setVgap(4); tags.setPadding(new Insets(4, 0, 4, 0)); for (String tag : new String[]{"JavaFX", "UI", "Layouts", "FXML", "Panes"}) { Label chip = new Label(tag); chip.setStyle("-fx-background-color: #e0e7ff; -fx-padding: 2 8 2 8; " + "-fx-background-radius: 12;"); tags.getChildren().add(chip); } // --- Editor area fills remaining space via AnchorPane --- AnchorPane editorPane = new AnchorPane(); TextArea area = new TextArea(); area.setPromptText("Start typing your note..."); AnchorPane.setTopAnchor(area, 0.0); AnchorPane.setBottomAnchor(area, 0.0); AnchorPane.setLeftAnchor(area, 0.0); AnchorPane.setRightAnchor(area, 0.0); editorPane.getChildren().add(area); // --- Compose the full screen --- VBox root = new VBox(10, avatarStack, tags, editorPane); root.setPadding(new Insets(12)); VBox.setVgrow(editorPane, Priority.ALWAYS); // editor takes leftover height stage.setScene(new Scene(root, 500, 400)); stage.setTitle("Combined Layout Demo"); stage.show(); } }
VBox.setVgrow tells a VBox to give any leftover vertical space to a specific child. Without it, the AnchorPane shrinks to its preferred size and the text area stays small. This pattern — a fixed-height header + a growing body — appears in nearly every desktop application.

Choosing the Right Pane

  • StackPane: overlays, cards with badges, loading spinners over content, tooltip-style pop-overs.
  • FlowPane: tag clouds, chip groups, dynamic toolboxes, wrapping image thumbnails, any collection whose item count varies at runtime.
  • AnchorPane: pinning controls to window edges, building resizable split layouts in FXML, positioning a floating action button in the corner of a panel.

Summary

You now have the full set of everyday JavaFX layout panes. StackPane stacks children in Z-order, letting you build composited UI elements with a single pane. FlowPane wraps children like text, adapting to available width or height at runtime. AnchorPane pins children to pane edges so they move and resize with the window. In the next lesson you will leave code-only layouts behind and meet FXML — a declarative XML format that lets Scene Builder generate all of this structure visually.