JTree 是 Swing 最強大也最複雜的元件之一。幸好 90% 場景只需「預設樹模型」(DefaultTreeModel + DefaultMutableTreeNode) 即可滿足。本文以 Trees.java 示範基本樹構建與按鈕動態新增子節點。
// 1. 建立根節點
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
// 2. 建立 JTree 並放入捲動面板
JTree tree = new JTree(root);
add(new JScrollPane(tree), BorderLayout.CENTER);
// 3. 取得模型以便後續操作
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
JButton btn = new JButton("新增子節點");
btn.addActionListener(e -> {
// 1. 準備新節點資料 (此處為示範陣列)
String[] newData = {"Colors", "Red", "Blue", "Green"};
DefaultMutableTreeNode newBranch = new DefaultMutableTreeNode(newData[0]);
for (int i = 1; i < newData.length; i++)
newBranch.add(new DefaultMutableTreeNode(newData[i]));
// 2. 取得目前選中的節點 (無選中則用根節點)
DefaultMutableTreeNode selected = (DefaultMutableTreeNode)
tree.getLastSelectedPathComponent();
if (selected == null) selected = root;
// 3. 透過模型插入 → 自動觸發 TreeModelEvent → JTree 更新視圖
model.insertNodeInto(newBranch, selected, 0); // 索引 0 表插在最前
});
JTree (View)
│
▼
DefaultTreeModel (Model) ──► TreeModelEvent ──► TreeModelListener (JTree 內部)
│
▼
DefaultMutableTreeNode (Node)
├── userObject: Object (業務資料)
├── children: Vector
└── parent: DefaultMutableTreeNode
| 需求 | 解決方向 | 關鍵類別/方法 |
|---|---|---|
| 自訂節點圖示 | 實作 TreeCellRenderer (繼承 DefaultTreeCellRenderer) | getTreeCellRendererComponent 依 userObject 類型回傳圖示 |
| 節點編輯/重命名 | tree.setEditable(true) + 自訂 TreeCellEditor | DefaultTreeCellEditor、TreeCellEditor 介面 |
| 拖放重排節點 | tree.setDragEnabled(true) + TransferHandler | 需處理 TreePath 序列化 |
| 大量資料延遲載入 | 實作 TreeModel 介面,getChild 時才查詢 DB | 避免一次性建立全樹節點物件 |
| 複選/勾選框節點 | 自訂 Renderer 繪製 CheckBox + 滑鼠監聽器切換狀態 | 狀態存於 userObject 或外部 Map |
| 搜尋/高亮節點 | tree.getNextMatch() 或遍歷 TreePath 配合 scrollPathToVisible() | TreeSelectionModel、DefaultTreeSelectionModel |
DefaultMutableTreeNode 為重量級物件 (含 Vector、父子雙向參考);超過 10 萬節點建議改虛擬模型。insertNodeInto/removeNodeFromParent 會觸發大量事件;批次操作可用 model.reload(parent) 一次通知。userObject (自訂 POJO),切勿繼承 DefaultMutableTreeNode 汙染模型。掌握「模型操作 → 事件通知 → 視圖自動更新」流程,即可輕鬆駕馭 JTree 建構從簡單目錄樹到複雜組織架構圖的各類應用。