JavaFX Fundamentals & the Scene Graph

Stage, Scene & the Scene Graph

18 min Lesson 3 of 12

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.
Primary stage ownership: The primary stage is created and owned by the JavaFX runtime. You must never call 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:

VBox root = new VBox(10); // 10 px spacing between children Scene scene = new Scene(root, 800, 600); stage.setScene(scene);

Key properties of Scene:

  • Root node — the single top-level layout container that fills the entire scene area.
  • Stylesheetsscene.getStylesheets().add(...) adds external CSS files that style the whole tree.
  • Fillscene.setFill(Color.DARKGRAY) sets the background colour of the scene (behind the root node).
  • Cursorscene.setCursor(Cursor.WAIT) changes the mouse pointer for the entire window.
Replace the root to swap views: Instead of opening a new window for a "settings" screen, call 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:

// Scene graph: BorderPane → (top: HBox → [Label, Button], center: TextArea) HBox toolbar = new HBox(8); Label titleLabel = new Label("Notes"); Button saveButton = new Button("Save"); toolbar.getChildren().addAll(titleLabel, saveButton); TextArea editor = new TextArea(); BorderPane root = new BorderPane(); root.setTop(toolbar); root.setCenter(editor); Scene scene = new Scene(root, 900, 600); stage.setScene(scene); stage.setTitle("Notes App"); stage.show();

The resulting tree looks like:

Scene └─ BorderPane (root) ├─ HBox (top) │ ├─ Label "Notes" │ └─ Button "Save" └─ TextArea (center)

Why a Tree? The Cascade of Properties

The tree structure is not arbitrary — it drives three powerful platform behaviours:

  1. CSS cascade: a style rule applied to a parent automatically affects all descendants, exactly like web CSS. Set a font on BorderPane and every child Label inherits it unless overridden.
  2. Coordinate space: each node's position is expressed relative to its parent. Move the parent and all children move with it — no arithmetic required.
  3. 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.
A node may only have one parent. If you add a node that is already in the tree to a second container, JavaFX silently removes it from the first. Attempting to share a node between two parents is a common layout bug — clone it instead.

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, or null for the root.
  • node.getScene() — returns the Scene this node belongs to, or null if not yet attached.
  • parent.getChildrenUnmodifiable() — read-only view of a parent's children list.
  • scene.lookup("#myId") — find any node by its CSS ID, like document.getElementById in the browser.
  • scene.lookupAll(".btn-primary") — find all nodes matching a CSS class selector.
// Assign IDs in code (or in FXML) for later lookup saveButton.setId("saveBtn"); // Later, from any code that has a scene reference: Button found = (Button) scene.lookup("#saveBtn");

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 Node objects 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.

ES
Edrees Salih
1 hour ago

We are still cooking the magic in the way!