樹形選單 是桌面應用程式中常見的導航元件,適合展示層級結構資料(如檔案目錄、組織架構、選單分類)。Java Swing 提供 JTree、DefaultMutableTreeNode、DefaultTreeModel 等核心類別,支援靈活的樹形結構建立與互動。本文將完整示範如何從零建立一個功能完整的樹形選單。
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class TreeMenuDemo extends JFrame implements TreeSelectionListener {
private JLabel statusLabel;
public TreeMenuDemo() {
super("文字編輯器選單示範");
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
Container container = getContentPane();
container.setLayout(new BorderLayout());
// 1. 建立根節點與一級子節點
DefaultMutableTreeNode root = new DefaultMutableTreeNode("文字編輯器");
DefaultMutableTreeNode fileMenu = new DefaultMutableTreeNode("檔案");
DefaultMutableTreeNode editMenu = new DefaultMutableTreeNode("編輯");
// 2. 建立樹模型並掛載一級節點
DefaultTreeModel treeModel = new DefaultTreeModel(root);
treeModel.insertNodeInto(fileMenu, root, root.getChildCount());
treeModel.insertNodeInto(editMenu, root, root.getChildCount());
// 3. 為「檔案」選單新增子項目
String[] fileItems = {"開啟", "儲存", "另存新檔", "關閉"};
for (String item : fileItems) {
DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(item);
treeModel.insertNodeInto(leaf, fileMenu, fileMenu.getChildCount());
}
// 4. 為「編輯」選單新增子項目
String[] editItems = {"剪下", "複製", "貼上"};
for (String item : editItems) {
DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(item);
treeModel.insertNodeInto(leaf, editMenu, editMenu.getChildCount());
}
// 5. 建立 JTree 並設定選擇模式
JTree tree = new JTree(treeModel);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(this);
tree.setRowHeight(22);
// 6. 自訂節點渲染樣式
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree.getCellRenderer();
renderer.setFont(new Font("微軟正黑體", Font.PLAIN, 14));
renderer.setBackgroundNonSelectionColor(Color.WHITE);
renderer.setBackgroundSelectionColor(new Color(255, 255, 200));
renderer.setBorderSelectionColor(Color.RED);
renderer.setTextNonSelectionColor(Color.BLACK);
renderer.setTextSelectionColor(Color.BLUE);
// 7. 加入捲動面板與狀態列
container.add(new JScrollPane(tree), BorderLayout.CENTER);
statusLabel = new JLabel("目前選擇的節點:", JLabel.CENTER);
statusLabel.setFont(new Font("微軟正黑體", Font.PLAIN, 14));
container.add(statusLabel, BorderLayout.SOUTH);
setVisible(true);
}
@Override
public void valueChanged(TreeSelectionEvent e) {
JTree tree = (JTree) e.getSource();
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if (selectedNode != null) {
statusLabel.setText("目前選擇的節點:" + selectedNode.toString());
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new TreeMenuDemo());
}
}
treeModel.insertNodeInto(childNode, parentNode, parentNode.getChildCount());
使用 getChildCount() 作為索引,確保新節點總是附加在父節點的最後位置,維持插入順序。
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
支援三種模式:
SINGLE_TREE_SELECTATION:單選(預設)CONTIGUOUS_TREE_SELECTION:連續多選DISCONTIGUOUS_TREE_SELECTION:不連續多選透過 DefaultTreeCellRenderer 可調整:
getTreeCellRendererComponent)TreeModelListener 監聽資料變更Drag and Drop 支援節點拖曳排序JTree.setCellEditor 實現節點就地編輯