javafx.scene.layout (JavaFX 28)
Description: declaration: module: javafx.graphics, package: javafx.scene.layout

# Package javafx.scene.layout

package javafx.scene.layout

Provides classes to support user interface layout. Each layout pane class supports a different layout strategy for its children and applications may nest these layout panes to achieve the needed layout structure in the user interface. Once a node is added to one of the layout panes, the pane will automatically manage the layout for the node, so the application should not position or resize the node directly; see "Node Resizability" for more details.

## Scene Graph Layout Mechanism

The scene graph layout mechanism is driven automatically by the system once the application creates and displays a `Scene`. The scene graph detects dynamic node changes which affect layout (such as a change in size or content) and calls `requestLayout()`, which marks that branch as needing layout so that on the next pulse, a top-down layout pass is executed on that branch by invoking `layout()` on that branch's root. During that layout pass, the `layoutChildren()` callback method will be called on each parent to layout its children. This mechanism is designed to maximize layout efficiency by ensuring multiple layout requests are coalesced and processed in a single pass rather than executing re-layout on on each minute change. Therefore, applications should not invoke layout directly on nodes.

## Node Resizability

The scene graph supports both resizable and non-resizable node classes. The `isResizable()` method on `Node` returns whether a given node is resizable or not. A resizable node class is one which supports a range of acceptable sizes (minimum <= preferred <= maximum), allowing its parent to resize it within that range during layout, given the parent's own layout policy and the layout needs of sibling nodes. Node supports the following methods for layout code to determine a node's resizable range:

        public Orientation getContentBias()
        public double minWidth(double height)
        public double minHeight(double width)
        public double prefWidth(double height)
        public double prefHeight(double width)
        public double maxWidth(double height)
        public double maxHeight(double width)

Non-resizable node classes, on the other hand, do not have a consistent resizing API and so are not resized by their parents during layout. Applications must establish the size of non-resizable nodes by setting appropriate properties on each instance. These classes return their current layout bounds for min, pref, and max, and the `resize()` method becomes a no-op.

Resizable classes: `Region`, `Control`, `WebView`
Non-Resizable classes: `Group`, `Shape`, `Text`

For example, a Button control (resizable) computes its min, pref, and max sizes which its parent will use to resize it during layout, so the application only needs to configure its content and properties:

        Button button = new Button("Apply");

However, a Circle (non-resizable) cannot be resized by its parent, so the application needs to set appropriate geometric properties which determine its size:

        Circle circle = new Circle();
        circle.setRadius(50);

## Resizable Range

Each resizable node class computes an appropriate min, pref, and max size based on its own content and property settings (it's 'intrinsic' size range). Some resizable classes have an unbounded max size (all layout panes) while others have a max size that is clamped by default to their preferred size (buttons) (See individual class documentation for the default range of each class). While these defaults are geared towards common usage, applications often need to explicitly alter or set a node's resizable range to achieve certain layouts. The resizable classes provide properties for overriding the min, pref and max sizes for this purpose.

For example, to override the preferred size of a ListView:

        listview.setPrefSize(200,300);

Or, to change the max width of a button so it will resize wider to fill a space:

        button.setMaxWidth(Double.MAX_VALUE);

For the inverse case, where the application needs to clamp the node's min or max size to its preferred:

        listview.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);

And finally, if the application needs to restore the intrinsically computed values:

        listview.setPrefSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);

## CSS Styling and Node Sizing

Applications cannot reliably query the bounds of a resizable node until it has been added to a scene because the size of that node may be dependent on CSS. This is because CSS is used to style many aspects of a node which affect it's preferred size (font, padding, borders, etc) and so the node cannot be laid out (resized) until CSS has been applied and the parent can access valid size range metrics. This is always true for Controls (and any panes that contain them), because they rely on CSS for their default style, even if no user-level style sheets have been set. Stylesheets are set at the Scene level, which means that styles cannot even be determined until a node's enclosing scene has been initialized. Once a Scene is initialized, CSS is applied to nodes on each pulse (when needed) just before the layout pass.

## Visual Bounds vs. Layout Bounds

A graphically rich user interface often has the need to make a distinction between a node's visual bounds and the bounds used for layout. For example, the tight visual bounds of a Text node's character glyphs would not work for layout, as the text would not be aligned and leading/trailing whitespace would be discounted. Also, sometimes applications wish to apply affects and transforms to nodes without disturbing the surrounding layout (bouncing, jiggling, drop shadows, glows, etc). To support this distinction in the scene graph, `Node` provides the `layoutBounds` property to define the 'logical' bounds of the node for layout and `boundsInParent` to define the visual bounds once all effects, clipping, and transforms have been applied.

These two bounds properties will often differ for a given node and `layoutBounds` is computed differently depending on the node class:

Bounds Computation Table
Node Type | Layout Bounds
--- | ---
`Shape`,`ImageView` | Includes geometric bounds (geometry plus stroke). Does NOT include effect, clip, or any transforms.
`Text` | logical bounds based on the font height and content width, including white space. can be configured to be tight bounds around chars glyphs by setting `boundsType`. Does NOT include effect, clip, or any transforms.
`Region`, `Control`, `WebView` | always `[0,0 width x height]` regardless of visual bounds, which might be larger or smaller than layout bounds.
`Group` | Union of all visible children's visual bounds (`boundsInParent`) Does NOT include effect, clip, or transforms set directly on group, however DOES include effect, clip, transforms set on individual children since those are included in the child's `boundsInParent`.

So for example, if a `DropShadow` is added to a shape, that shadow will not be factored into layout by default. Or, if a `ScaleTransition` is used to pulse the size of a button, that pulse animation will not disturb layout around that button. If an application wishes to have the effect, clip, or transform factored into the layout of a node, it should wrap that node in a Group.

## Layout Orientation

The layout orientation for a branch of the scene graph is controlled by the `Scene.nodeOrientation` and `Node.nodeOrientation` properties. A value set on a `Scene` applies to its root, and a value set on any `Node` applies to that node and its descendants. It is typically left-to-right by default, but can be right-to-left depending on the locale of the operating system.

For layout containers, the effective orientation determines how children are ordered and how horizontal positions are interpreted. In a left-to-right orientation, the first child usually appears at the left edge and subsequent children flow to the right. Similarly, in a right-to-left orientation, the first child usually appears at the right edge and subsequent children flow to the left. When a container exposes named regions, the `left` region refers to the leading edge of the container, and the `right` region refers to the trailing edge of the container. In right-to-left mode, the `left` region will therefore be laid out on the right side, and the `right` region will be laid out on the left side.

Authors typically do not need to account for layout orientation when laying out nodes. In right-to-left mode, a mirroring transform is automatically applied to nodes, flipping the visual flow in the horizontal direction. If this behavior is not desired, nodes can override `Node.usesMirroring()` and return `false`.

## Pixel Snapping

In JavaFX, layout coordinates use `double` values, which means that a position or size can be fractional. Mapping fractional coordinates onto a physical screen can introduce blurriness if the edge of a node falls somewhere between physical pixels. JavaFX uses snapping to fix this problem; it ensures that the bounds of scene graph nodes do not fall between physical pixels on the screen.

This section provides guidance for authors of custom `Region` or `SkinBase<C extends Control>` implementations that override measurement and layout methods such as `Parent.layoutChildren()`, `Region.computeMinWidth(double)`, `Region.computeMinHeight(double)`, `Region.computePrefWidth(double)`, `Region.computePrefHeight(double)`, as well as the corresponding `SkinBase` methods.

### Logical vs. pixel coordinates

Layout is expressed in logical coordinates, and the horizontal and vertical render scales of a window convert logical units to pixels in the window's rendering buffer:

        physical pixels = logical units * render scale

At a render scale of `1.0`, one logical unit is one pixel. At a render scale of `1.5`, one pixel is `1 / 1.5` ≈ `0.6667` logical units. A correctly snapped value is therefore not necessarily an integer, and simply rounding coordinates to integers is wrong. Conceptually, snapping applies a rounding operation in pixels and converts the result back to logical units:

        snappedValue = round(logicalValue * renderScale) / renderScale

The render scales in the two axes can be different, and they can change when a window moves between screens. A `Region` that is not attached to a window uses a render scale of `1.0`. Applications should use the snapping methods on `Region` instead of implementing the formula above or caching its result. The built-in methods use the appropriate current render scale and account for floating-point error near pixel boundaries.

### Choosing the snapping operation

`Region` provides three pairs of axis-specific snapping methods. Their names describe the semantic role of the value being snapped, which influences the snapping direction:

Snapping operations
Meaning | Method | Rounding | Example
--- | --- | --- | ---
Position of a child | `snapPositionX` or `snapPositionY` | Nearest pixel | The final `x` or `y` passed to `relocate`
Size of a child | `snapSizeX` or `snapSizeY` | Up to the next pixel | The final `width` or `height` passed to `resize`
Empty space | `snapSpaceX` or `snapSpaceY` | Nearest pixel | An inset, a padding, or a gap between adjacent children

The reason for the different snapping methods is semantic:

- A position is rounded to the nearest pixel so that an edge stays close to its requested coordinate.
- Sizes use ceiling so that snapping itself does not reduce the measured content allocation.
- Empty space can usually become slightly smaller without losing content.

The snapped inset methods return the combined border inset and padding; custom controls should normally use these methods instead of snapping raw insets manually.

### Why snapped content can still look blurry

Enabling pixel snapping on a region does not guarantee that the region or its descendants will be rendered on pixel boundaries. The `snapToPixel` property controls layout calculations performed by that region only; it is not inherited from the parent and does not affect whether children snap their contents. A region owns the position and size it allocates to a child; the child owns the layout of its own descendants.

For example, setting only the child's property does not repair a fractional position assigned by its parent:

    parent.setSnapToPixel(false);
    child.setSnapToPixel(true);

    // At scale 1.0, the parent places the child between pixels
    child.relocate(10.5, 20.5);

In this case, even if the child snaps its descendants in its local coordinates, the entire child subtree remains shifted by half a pixel. Conversely, a parent can allocate a child pixel-aligned outer bounds even when that child has disabled snapping for its own layout.

Transforms are applied after the layout has been computed. For example, at render scale `1.0`, the following translation undoes the alignment established during layout:

    child.relocate(snapPositionX(10), snapPositionY(20));
    child.setTranslateX(0.5); // The rendered X coordinate is now between pixels

Therefore, if content appears blurry despite pixel snapping being enabled, check both how its ancestors position and size it and whether transforms affect its final rendered position.

### Why snapping is difficult

There is no single correct direction in which to round a value, and no single place in a layout algorithm where snapping must occur. Since a value can represent a position, content size, empty space, or a combined sum of such elements, each semantic role can require a different decision:

- Snapping too early can lose precision, while snapping too late can introduce errors.
- Snapping several children independently can avoid clipping, but the region's measurement and layout methods must use consistent calculations so that the computed content size includes those allocations.

Additionally, adding or subtracting already-snapped values can introduce floating-point drift that may cause a later snapping operation to incorrectly add or remove a pixel. Calling a snapping method somewhere in a layout algorithm is not, by itself, evidence that the resulting value is correctly snapped. Implementing correct snapping therefore requires a great deal of caution to get it right.

### Checklist for correct snapping

1. Use the axis-specific snapping method.
   A horizontal value uses the X scale and a vertical value uses the Y scale. This matters when those scales differ:

       double left = snapSpaceX(margin.getLeft()); // Correct
       double top = snapSpaceY(margin.getTop());   // Correct

       double top = snapSpaceX(margin.getTop());   // Incorrect axis
       double gap = snapSpace(rawGap);             // Deprecated and ambiguous

2. Identify the owner of the snapping policy.
   The region arranging a child owns the child's position and its allocated size; use that region's `isSnapToPixel` policy. For example, write:

       // Correct: this region owns the child's position
       double x = snapPositionX(computeChildX());
       double y = snapPositionY(computeChildY());
       child.relocate(x, y);

       // Incorrect: the child's snapping policy does not control placement by its parent
       double x = child.snapPositionX(computeChildX());
       double y = child.snapPositionY(computeChildY());
       child.relocate(x, y);

3. Classify each value before choosing a snapping method.
   Positions and spaces use nearest-pixel rounding; content sizes use ceiling. This distinction prevents gaps from growing unnecessarily and content from being clipped:

       double x = snapPositionX(rawX);       // coordinate
       double gap = snapSpaceX(rawGap);      // empty space
       double width = snapSizeX(rawWidth);   // content size

       // Incorrect: a 0.1-unit gap becomes a full pixel
       double gap = snapSizeX(0.1);

4. Re-snap calculations whose exact result is known to be pixel-aligned.
   If every operand of an addition or subtraction has already been snapped, the idealized mathematical result is also pixel-aligned. However, floating-point arithmetic can cause that result to be slightly off the pixel grid. In this situation, the fractional remainder is known to be arithmetic drift rather than an intentional offset, so re-snap the final result using nearest-pixel rounding before returning it or using it in another layout calculation:
   - Re-snap a coordinate with `snapPositionX/Y`.
   - Re-snap empty space (gaps, margins, padding) or an allocated content span with `snapSpaceX/Y`.
   - Do not use `snapSizeX/Y` to snap such a result, because ceiling can turn positive floating-point drift into an extra pixel.
   For example, write:

       double firstWidth = snapSizeX(firstChildWidth);
       double gapWidth = snapSpaceX(getGap());
       double secondWidth = snapSizeX(secondChildWidth);

       // Correct: re-snap the final allocated span with snapSpaceX after arithmetic
       double allocatedWidth = snapSpaceX(firstWidth + gapWidth + secondWidth);

       // Correct: coordinate calculated from snapped values is re-snapped as a position
       double childX = snapPositionX(snappedLeftInset() + allocatedWidth);

       // Incorrect: snapSizeX can turn floating-point noise into an extra pixel
       double allocatedWidth = snapSizeX(firstWidth + gapWidth + secondWidth);

       // Incorrect: the sum of snapped values can add floating-point drift
       double allocatedWidth = firstWidth + gapWidth + secondWidth;

5. Snap independent allocations independently.
   If two independent pieces of content each need their own pixels, snapping only their sum can under-allocate layout space. At scale `1.0`, two content widths of `0.4` each require one pixel, while their combined raw width of `0.8` would be rounded to only one pixel:

       // Correct: each content item receives an independent allocation
       double total = snapSpaceX(snapSizeX(firstWidth) + snapSizeX(secondWidth)); // 2.0

       // Incorrect: the raw sum is treated as one allocation
       double total = snapSpaceX(firstWidth + secondWidth); // 1.0

   Only the correct example gives each child its own snapped allocation before adding them; the outer `snapSpaceX` follows the preceding re-snapping rule. This independent allocation rule also applies to distinct margins and gaps.

   Note that this only applies to independent allocations. If several children must fit within a fixed allocated space, the algorithm must consider all children together and coordinate rounding children up or down so that their sum does not exceed the allocated space.

6. Do not repeatedly snap the same semantic value.
   Preserve precision while refining a value and call the appropriate snapping method only after the refinement. Repeated snapping is especially dangerous for content sizes because `snapSizeX/Y` uses ceiling. For example, if an adjustment is part of the same content measurement:

       // Correct: compute all terms first, then allocate the width once
       double width = snapSizeX(measuredWidth + measurementAdjustment);

       // Incorrect: snapping early throws away information and the second snapSizeX can add another pixel
       double width = snapSizeX(snapSizeX(measuredWidth) + measurementAdjustment);

   At scale `1.0`, if both values are `0.2`, the first form returns `1.0`, while the second (incorrect) form returns `2.0`. This rule does not conflict with the preceding rule: two independent pieces of content are two allocations, while two intermediate terms describing one piece of content are one allocation.
7. Use the same snapped dependent dimension for measurement and layout.
   Content-biased nodes have an order dependency between width and height. For example, for a horizontally-biased child, height depends on width. Establish the snapped width first and pass that exact width to the height calculation:

       static double boundedSize(double value, double min, double max) {
           return Math.min(Math.max(value, min), Math.max(min, max));
       }

       // This assumes the child should fill the available width
       double rawChildWidth = boundedSize(
           availableWidth,
           child.minWidth(-1),
           child.maxWidth(-1));

       // Correct:
       // 1. Snap the width the child will actually receive
       double snappedChildWidth = snapSizeX(rawChildWidth);

       // 2. Use the snapped width for every dependent height measurement
       double rawChildHeight = boundedSize(
           child.prefHeight(snappedChildWidth),
           child.minHeight(snappedChildWidth),
           child.maxHeight(snappedChildWidth));

       // 3. Snap the height the child will receive
       double snappedChildHeight = snapSizeY(rawChildHeight);

       // Incorrect:
       // 1. The dependent height is measured for rawChildWidth
       double rawChildHeight = boundedSize(
           child.prefHeight(rawChildWidth),
           child.minHeight(rawChildWidth),
           child.maxHeight(rawChildWidth));

        // 2. rawChildHeight was measured for a width that the child might not
        //    actually receive, which makes the snapped value potentially wrong
        double snappedChildHeight = snapSizeY(rawChildHeight);

8. Deliberately apply the snapping policy to values determined by the parent.
   Since a region's position and allocated size are determined by its parent (and the `isSnapToPixel` policy of its parent), it must not reposition or resize itself. If the allocated width or height is not pixel-aligned, the region cannot both preserve the exact allocation and make its complete bounds pixel-aligned. The region must choose how to lay out its children according to its fitting and overflow policy. For example, a fill policy that accepts a slight underflow or overflow can round the available span to the nearest pixel before laying out a resizable child:

       // Snap own width and height to determine the content rectangle for children
       double availableWidth = snapSpaceX(getWidth());
       double availableHeight = snapSpaceY(getHeight());

       // Assumes a completely unconstrained, resizable child
       child.resizeRelocate(0, 0, availableWidth, availableHeight);

9. Property values should not be snapped when set, only when they are consumed.
   The setter of a geometric property should not snap the value, and the getter should return the exact value set by the application:

       // Correct
       public void setGap(double value) {
           gap.set(value);
       }

       protected void layoutChildren() {
           double snappedGap = snapSpaceX(getGap());
           // use snappedGap for this horizontal allocation
       }

       // Incorrect: this loses the requested value and uses whichever scale is
       //            current when the setter happens to be called
       public void setGap(double value) {
           gap.set(snapSpaceX(value));
       }

- Related Packages
  Package
  Description
  javafx.scene
  Provides the core set of base classes for the JavaFX Scene Graph API.
- Class
  Description
  AnchorPane
  AnchorPane allows the edges of child nodes to be anchored to an offset from the anchor pane's edges.
  Background
  The Background of a `Region`.
  BackgroundFill
  The fill and associated properties that direct how to fill the background of a `Region`.
  BackgroundImage
  Defines properties describing how to render an image as the background to some `Region`.
  BackgroundPosition
  Represents the position of a `BackgroundImage` within the `Region`'s drawing area.
  BackgroundRepeat
  Enumeration of options for repeating images in backgrounds
  BackgroundSize
  Defines the size of the area that a BackgroundImage should fill relative to the Region it is styling.
  Border
  The border of a `Region`.
  BorderImage
  Defines properties describing how to render an image as the border of some Region.
  BorderPane
  BorderPane lays out children in top, left, right, bottom, and center positions.
  BorderRepeat
  Enum indicating the repetition rules for border images.
  BorderStroke
  Defines the stroke to use on a `Border` for styling a `Region`.
  BorderStrokeStyle
  Defines the style of the stroke to use on one side of a BorderStroke.
  BorderWidths
  Defines widths for four components (top, right, bottom, and left).
  ColumnConstraints
  Defines optional layout constraints for a column in a `GridPane`.
  ConstraintsBase
  The base class for defining node-specific layout constraints.
  CornerRadii
  Defines the radii of each of the four corners of a BorderStroke.
  FlowPane
  FlowPane lays out its children in a flow that wraps at the flowpane's boundary.
  GridPane
  GridPane lays out its children within a flexible grid of rows and columns.
  HBox
  HBox lays out its children in a single horizontal row.
  HeaderBar
  A client-area header bar that is used as a replacement for the system-provided header bar in stages with the `StageStyle.EXTENDED` style.
  HeaderButtonType
  Identifies the semantic type of a button in a custom `HeaderBar`, which enables integrations with the platform window manager.
  HeaderDragType
  Specifies how a `Node` participates in `HeaderBar` draggable-area hit testing.
  Pane
  Base class for layout panes which need to expose the children list as public so that users of the subclass can freely add/remove children.
  Priority
  Enumeration used to determine the grow (or shrink) priority of a given node's layout area when its region has more (or less) space available and multiple nodes are competing for that space.
  Region
  Region is the base class for all JavaFX Node-based UI Controls, and all layout containers.
  RowConstraints
  Defines optional layout constraints for a row in a `GridPane`.
  StackPane
  StackPane lays out its children in a back-to-front stack.
  TilePane
  TilePane lays out its children in a grid of uniformly sized "tiles".
  VBox
  VBox lays out its children in a single vertical column.