Stage, Scene & the Scene Graph
Stage, Scene & the Scene Graph
Every visible JavaFX application is built from three interlocking concepts: the Stage, the Scene, and the Scene Graph. Understanding exactly what each one is — and how they relate — is the mental model that makes every subsequent layout, style, and event decision click into place.
The Stage
A Stage is a top-level window. The JavaFX runtime creates one for you — the primary stage — and passes it to your start(Stage stage) method. You can also construct additional Stage instances whenever you need a second window (a dialog, a tool palette, a secondary monitor view).
The Stage class wraps the native OS window. Its most commonly configured properties are:
stage.setTitle("My App")— the window title bar text.stage.setWidth(800)/stage.setHeight(600)— initial pixel dimensions.stage.setResizable(false)— lock the user from resizing.stage.initStyle(StageStyle.UNDECORATED)— remove the OS chrome entirely (useful for splash screens).stage.initModality(Modality.APPLICATION_MODAL)— block input to other windows (modal dialog pattern).stage.show()— make the window visible; until this is called nothing appears on screen.
new Stage() to replace it — configure and show the one that is handed to you.
The Scene
A Scene is the content holder that lives inside a Stage. One scene is active at any moment; you can swap scenes to implement page-style navigation without opening new windows. A scene is constructed with a root node and optional preferred dimensions:
Key properties of Scene:
- Root node — the single top-level layout container that fills the entire scene area.
- Stylesheets —
scene.getStylesheets().add(...)adds external CSS files that style the whole tree. - Fill —
scene.setFill(Color.DARKGRAY)sets the background colour of the scene (behind the root node). - Cursor —
scene.setCursor(Cursor.WAIT)changes the mouse pointer for the entire window.
stage.getScene().setRoot(settingsPane). It is fast, keeps the same stage and scene, and preserves any stylesheets you already attached to the scene.
The Scene Graph
The scene graph is the tree of Node objects whose root is the scene's root node. Every visual or interactive element in JavaFX — a button, a label, an image, a rectangle, a layout pane, a media player — is a Node. They are arranged in a parent–child hierarchy:
- Parent nodes (subclasses of
Parent) can have children:VBox,HBox,BorderPane,StackPane,Group, etc. - Leaf nodes cannot have children:
Button,Label,Rectangle,ImageView, etc.
Here is a small scene graph in code:
The resulting tree looks like:
Why a Tree? The Cascade of Properties
The tree structure is not arbitrary — it drives three powerful platform behaviours:
- CSS cascade: a style rule applied to a parent automatically affects all descendants, exactly like web CSS. Set a font on
BorderPaneand every childLabelinherits it unless overridden. - Coordinate space: each node's position is expressed relative to its parent. Move the parent and all children move with it — no arithmetic required.
- Event bubbling: mouse clicks and key presses travel down the tree (capture phase) and then up (bubble phase), so a single listener on a container can intercept events from any descendant.
Traversing and Inspecting the Tree
You rarely need to walk the tree manually, but it helps to know the API exists. Every Node exposes:
node.getParent()— returns the direct parent, ornullfor the root.node.getScene()— returns theScenethis node belongs to, ornullif not yet attached.parent.getChildrenUnmodifiable()— read-only view of a parent's children list.scene.lookup("#myId")— find any node by its CSS ID, likedocument.getElementByIdin the browser.scene.lookupAll(".btn-primary")— find all nodes matching a CSS class selector.
Live vs. Unattached Nodes
A node that has been added to the scene graph and is part of a showing stage is called live. Once live, the CSS engine styles it, the layout engine measures and positions it, and the rendering engine paints it every frame. A node that you created but have not yet added is unattached — it exists in memory but is invisible and unstyled. This distinction matters when you try to measure a node's size before it has been laid out: call node.applyCss() and node.layout() first if you need dimensions before the first rendering pulse.
Putting It All Together
The mental model is a clean three-layer sandwich:
- Stage — the OS window frame (title bar, decorations, modal state).
- Scene — the content canvas inside the stage (size, background fill, CSS stylesheets).
- Scene Graph — the tree of
Nodeobjects that define what is actually displayed and interactive.
Every feature you build in JavaFX — custom controls, animations, data bindings, drag-and-drop — operates on this tree. Knowing how to construct it, navigate it, and reason about parent–child relationships is the foundation everything else rests on.