這篇用劇場演出的比喻,整理 JavaFX 中六個常用概念的關係:Application、Stage、Scene、Node、Layout 與 Control。它們可以濃縮成一條主線:Application 管理應用程式,Stage 承載視窗,Scene 描述場景,Node 組成場景樹,Layout 安排位置,Control 提供互動能力。
JavaFX 的常用類別可以分成六個互相連接的概念:應用 Application、舞台 Stage、場景 Scene、節點 Node、布局 Layout 和控制項 Control。
整個關係可以濃縮成一句話:
Application 是導演,Stage 是劇場舞台,Scene 是一齣戲的場景,Node 是舞台上的演員與道具
Node 是 JavaFX 場景樹中的基本節點;在這篇先關注兩種常見角色:觀眾容易注意到、可以直接互動的 Control,以及不容易被注意到、負責安排其他 Node 位置的 Layout。更精確地說,Layout 與 Control 都是 Node 的不同子類別。
Layout 是綠幕演員,Control 則是可以直接互動的專業演員。
前面已經用過的 Layout 有 VBox、HBox、GridPane;Control 有 Label、Button、TextField 和 TextArea。把這層關係畫出來會是:
Application
│
│ 管理整個演出
▼
Stage
│
│ 裝上一齣戲
▼
Scene
│
│ 放入舞台上的東西
▼
Node
├── Layout
│ ├── VBox
│ ├── HBox
│ └── GridPane
│
├── Control
│ ├── Button
│ ├── Label
│ ├── TextField
│ └── TextArea

Application 像是一齣戲的導演,負責決定何時開始演出、準備哪些演員與道具,以及結束時如何收場。它是「負責整齣戲從開演到結束的人」。
public class MyApp extends Application {
@Override
public void start(Stage stage) {
// 開始準備演出
}
public static void main(String[] args) {
launch();
}
}
導演指導了整個流程:
Application
↓
「演出開始了!」
↓
準備 Stage
↓
準備 Scene
↓
安排演員 Node
↓
讓 Stage 開演
最重要的方法就是:
start(Stage stage)
「舞台已經準備好了,可以開始演這齣戲的第一個場景。」

Stage 是表演的地方。在桌面環境中,它就是應用程式的視窗。一個應用程式可以有一個或多個 Stage,各自承載不同或相同的 Scene。
┌──────────────────────────────┐
│ Calculator □ × │
├──────────────────────────────┤
│ │
│ JavaFX App │
│ │
└──────────────────────────────┘
它負責的是:
例如:
stage.setTitle("Calculator");
stage.setScene(scene);
stage.show();
換成導演語言:

電影或舞台劇可以分成不同場景。以美國動畫片《腦筋急轉彎》為例:
關鍵評論網:「三幕劇」形式於電影中的組成與調配
同一個舞台可以換上不同場景。尚未登入的使用者先演出登入場景(序幕):
stage.setScene(loginScene);
登入完成以後再換成主要場景(第一幕):
stage.setScene(mainScene);
因此:
同一個舞台 Stage
│
├── Scene:登入畫面
│
├── Scene:主畫面
│
└── Scene:設定畫面
就像同一座劇場:
序幕演「登入」
第一幕換成「主畫面」
第二幕演「設定」
Scene 確定這一幕的內容後,還需要一個根節點(root Node)放入實際的畫面元件。接下來就從 Node 開始,看舞台上的演員與道具如何組成場景樹。
「只要它是場景中可以被 JavaFX 管理、定位、顯示的東西,就可以把它理解成 Node。」
例如:
Button button;
Label label;
TextField textField;
ImageView image;
VBox vbox;

假設你有三個演員:
如果全部丟到舞台:
Alice
Charlie
Bob
很亂。所以需要一種方式告訴演員:
「你站這裡,你站那裡,這三個人排成一列。」
這很像表演舞台上經常標記的站位點,也就是 Layout。
VBox root = new VBox();
root.getChildren().addAll(
button1,
button2,
button3
);
它說:
┌─────────────────┐
│ Button 1 │
│ │
│ Button 2 │
│ │
│ Button 3 │
└─────────────────┘
HBox root = new HBox();
它說:
Button 1 Button 2 Button 3
Layout 的核心職責不是「演戲」,而是:「安排 Node 在舞台上的位置。」
而且 Layout 自己也是 Node。
所以:
VBox
│
├── Button
├── Label
└── HBox
├── Button
└── Button
完全可以。
因為:Layout 本身也是舞台上的一個 Node,而且它還可以裝其他 Node。因為可以裝下其他 Node,通常也稱作「容器」。這也是為什麼 JavaFX 可以建立一棵場景樹:
Scene
│
└── VBox
│
├── TextField
│
├── HBox
│ ├── Button
│ ├── Button
│ └── Button
│
└── HBox
├── Button
├── Button
└── Button
因為 Layout 通常不直接和觀眾互動,所以我認為它也很像綠幕演員。

可以把 Control 想成「具有標準互動能力的演員」。例如 Button、TextField 和 CheckBox。以 Button 為例,它知道:

一個計算機的演出過程會是
這些演員會接受觀眾互動:
觀眾點擊 Button
↓
Button 收到事件
↓
Event Handler
↓
Calculator 執行計算
↓
TextField 更新
Application 決定「演什麼」;Stage 提供「在哪裡演」;Scene 決定「這一幕長什麼樣」;Node 是「舞台上的東西」;Layout 決定「東西站哪裡」;Control 則是「能跟觀眾互動的東西」。
在 CalcFX 中,Application 建立 Stage,Stage 放入 Scene,Scene 的根節點是 GridPane;GridPane 安排 TextField 與 Button 的位置,而 TextField 和 Button 則負責顯示內容與接受使用者操作。