最簡單的樹:DefaultMutableTreeNode 構建節點
DefaultMutableTreeNode root = new DefaultMutableTreeNode("中國");
DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("廣東");
guangdong.add(new DefaultMutableTreeNode("佛山"));
guangdong.add(new DefaultMutableTreeNode("汕頭"));
root.add(guangdong);
JTree tree = new JTree(root);
tree.putClientProperty("JTree.lineStyle", "None"); // 無連線
tree.setShowsRootHandles(true); // 顯示根節點展開圖標
可編輯、拖拽、增刪節點
啟用編輯
tree.setEditable(true);
滑鼠拖拽移動節點
TreePath movePath;
MouseListener ml = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
movePath = tree.getPathForLocation(e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
TreePath target = tree.getPathForLocation(e.getX(), e.getY());
if (target != null && movePath != null && !movePath.equals(target)) {
if (movePath.isDescendant(target)) return; // 禁止拖到子節點
((DefaultMutableTreeNode)target.getLastPathComponent())
.add((DefaultMutableTreeNode)movePath.getLastPathComponent());
tree.updateUI();
}
}
};
tree.addMouseListener(ml);
按鈕操作:新增兄弟/子節點、刪除、重命名
// 新增兄弟節點
DefaultMutableTreeNode parent = (DefaultMutableTreeNode)selected.getParent();
model.insertNodeInto(newNode, parent, parent.getIndex(selected)+1);
// 新增子節點
selected.add(newNode); // 或 model.insertNodeInto(newNode, selected, selected.getChildCount());
// 刪除節點
model.removeNodeFromParent(selected);
// 重命名
tree.startEditingAtPath(tree.getSelectionPath());
自定義節點圖標:擴展 DefaultTreeCellRenderer
封裝節點資料
class NodeData {
int nodeType; String nodeData;
NodeData(int t, String d) { nodeType=t; nodeData=d; }
public String toString() { return nodeData; }
}
interface DBObjectType { int ROOT=0, DATABASE=1, TABLE=2, COLUMN=3, INDEX=4; }
渲染器實現
class MyRenderer extends DefaultTreeCellRenderer {
ImageIcon rootIcon = new ImageIcon("icon/root.gif");
ImageIcon dbIcon = new ImageIcon("icon/database.gif");
ImageIcon tableIcon = new ImageIcon("icon/table.gif");
ImageIcon colIcon = new ImageIcon("icon/column.gif");
ImageIcon idxIcon = new ImageIcon("icon/index.gif");
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
NodeData data = (NodeData) node.getUserObject();
ImageIcon icon = switch (data.nodeType) {
case DBObjectType.ROOT -> rootIcon;
case DBObjectType.DATABASE -> dbIcon;
case DBObjectType.TABLE -> tableIcon;
case DBObjectType.COLUMN -> colIcon;
case DBObjectType.INDEX -> idxIcon;
default -> null;
};
setIcon(icon);
return this;
}
}
套用渲染器
tree.setCellRenderer(new MyRenderer());
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(tree);
關鍵提示
- 節點資料請封裝為 `UserObject`,勿直接 `toString()` 硬編碼。
- 拖拽移動本質是「從原父節點移除 → 加入新父節點」,`DefaultMutableTreeNode.add()` 已自動處理移除。
- 大量節點時考慮 `TreeModel` 實作延遲載入(懶加載)。