Chris_D_Turk Chris_D_Turk - 1 year ago 109
Java Question

JavaFX - Bind stage size to the root node's preferred size

I would like to automatically adjust the width/height of a

whenever the preferred width/height of the
's root node changes.

It's a small utility window (not resizable by the user) that contains multiple
s and the window's height should increase when one of these TitledPanes is expanded (otherwise the TitlePane's content may be out of bounds).

Unfortunately I could only find
, which initially sets the window's size to the root's preferred size.

Is there a way to permanently bind the Stage size to the root node size?

Answer Source

Based on DVarga's example I crafted the following "solution":
A InvalidationListener is installed on the heightProperty of every child node that may shrink/grow in height (two TitlePanes in this example).
When a heightProperty is invalidated, the height of the containing window gets recalculated (also honering window decorations).


public class SampleApp extends Application {

    public void start(Stage primaryStage) throws Exception {
        final Label lbl1 = new Label("content");
        final TitledPane tp1 = new TitledPane("First TP", lbl1);

        final Label lbl2 = new Label("more content");
        final TitledPane tp2 = new TitledPane("Second TP", lbl2);

        final VBox rootPane = new VBox(tp1, tp2);

        tp1.heightProperty().addListener((InvalidationListener) observable -> {

        tp2.heightProperty().addListener((InvalidationListener) observable -> {

        final Scene scene = new Scene(rootPane);

    private void updateWindowHeight(final VBox rootPane) {
        final Scene scene = rootPane.getScene();
        if (scene == null) 
        final Window window = scene.getWindow();
        if (window == null)
        final double rootPrefHeight = rootPane.prefHeight(-1);
        final double decorationHeight = window.getHeight() - scene.getHeight(); // window decorations
        window.setHeight(rootPrefHeight + decorationHeight);

    public static void main(String[] args) {

Although it works as intended, there are some major drawbacks with this solution:

  • You have to install listeners on every node that might shrink/grow in size
  • From a CCD perspective this just wrong: Child-Nodes should not be responsible for sizing the stage they are contained by.

I couldn't get a cleaner solution to work. javafx.stage.Stage and javafx.scene.Scene are just too obstructed (possible extension points are final or package-private) to implement this feature where it belongs to.

Using just window.sizeToScene() instead of

final double rootPrefHeight = rootNode.prefHeight(-1);
final double decorationHeight = window.getHeight() - scene.getHeight();
window.setHeight(rootPrefHeight + decorationHeight);

generates a lot less "stutter" when adjusting the window size!