JTree 是 Swing 组件库中的树形结构组件,用于展示层级数据(如文件系统、组织结构图等)。
基本内容
-
节点(Node)
- 树形结构的基本单元,分为叶节点(无子节点)和分支节点(有子节点)。
- 常用实现类:
DefaultMutableTreeNode
。
-
模型(TreeModel)
- 管理节点的层级关系和数据。
- 常用实现类:
DefaultTreeModel
。
-
渲染器(TreeCellRenderer)
- 自定义节点的显示样式(文本、图标、颜色等)。
-
监听器(TreeSelectionListener)
- 监听节点选择事件。
核心类与方法
1. DefaultMutableTreeNode
import javax.swing.tree.DefaultMutableTreeNode;
// 创建节点
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1");
DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child 2");
// 添加子节点
root.add(child1);
root.add(child2);
2. DefaultTreeModel
import javax.swing.tree.DefaultTreeModel;
// 创建树模型
DefaultTreeModel model = new DefaultTreeModel(root);
// 动态添加节点
DefaultMutableTreeNode grandchild = new DefaultMutableTreeNode("Grandchild");
child1.add(grandchild);
model.nodeStructureChanged(child1); // 通知模型更新
3. JTree 基本用法
import javax.swing.JTree;
import javax.swing.JScrollPane;
import javax.swing.JFrame;
// 创建 JTree
JTree tree = new JTree(model);
// 将树添加到滚动面板
JScrollPane scrollPane = new JScrollPane(tree);
// 显示在窗口中
JFrame frame = new JFrame("JTree Example");
frame.add(scrollPane);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
进阶用法
1. 自定义渲染器
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.Component;
class CustomRenderer extends DefaultTreeCellRenderer {
@Override
public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
// 根据节点内容设置图标或文本
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
if (leaf) {
setText("Leaf: " + node.getUserObject());
} else {
setText("Branch: " + node.getUserObject());
}
return this;
}
}
// 使用自定义渲染器
tree.setCellRenderer(new CustomRenderer());
2. 监听节点选择事件
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeSelectionEvent;
tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)
tree.getLastSelectedPathComponent();
if (selectedNode != null) {
System.out.println("Selected: " + selectedNode.getUserObject());
}
}
});
3. 展开 / 折叠节点
// 展开所有节点
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
// 折叠指定节点
tree.collapseRow(1);
常见场景
- 文件浏览器
使用File
类构建文件系统树。 - 配置面板
展示多级配置项。 - 组织结构图
展示公司部门层级。
注意事项
-
性能优化
- 大数据量时使用
TreeModel
的懒加载机制(如数据库分页查询)。 - 使用
TreeWillExpandListener
控制节点展开逻辑。
- 大数据量时使用
-
线程安全
- Swing 组件非线程安全,更新树结构需在事件调度线程(EDT)中进行:
javax.swing.SwingUtilities.invokeLater(() -> { // 更新树模型的代码 });
- Swing 组件非线程安全,更新树结构需在事件调度线程(EDT)中进行:
示例代码
下面是一个完整的 JTree 示例,包含节点添加、自定义渲染和事件监听:
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.*;
public class JTreeDemo {
public static void main(String[] args) {
// 创建根节点
DefaultMutableTreeNode root = new DefaultMutableTreeNode("My Computer");
// 创建子节点
DefaultMutableTreeNode diskC = new DefaultMutableTreeNode("Local Disk (C:)");
DefaultMutableTreeNode diskD = new DefaultMutableTreeNode("Local Disk (D:)");
// 添加文件夹到 C 盘
DefaultMutableTreeNode documents = new DefaultMutableTreeNode("Documents");
DefaultMutableTreeNode downloads = new DefaultMutableTreeNode("Downloads");
diskC.add(documents);
diskC.add(downloads);
// 添加文件到 Downloads
documents.add(new DefaultMutableTreeNode("Resume.docx"));
documents.add(new DefaultMutableTreeNode("Project Report.pdf"));
// 添加子节点到根节点
root.add(diskC);
root.add(diskD);
// 创建树模型和 JTree
DefaultTreeModel model = new DefaultTreeModel(root);
JTree tree = new JTree(model);
// 设置自定义渲染器
tree.setCellRenderer(new CustomRenderer());
// 添加节点选择监听器
tree.getSelectionModel().addTreeSelectionListener(e -> {
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)
tree.getLastSelectedPathComponent();
if (selectedNode != null) {
System.out.println("Selected: " + selectedNode.getUserObject());
}
});
// 创建按钮面板
JPanel buttonPanel = new JPanel();
JButton addButton = new JButton("Add Node");
JButton deleteButton = new JButton("Delete Node");
buttonPanel.add(addButton);
buttonPanel.add(deleteButton);
// 添加按钮事件
addButton.addActionListener(e -> {
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)
tree.getLastSelectedPathComponent();
if (selectedNode != null) {
String newNodeName = JOptionPane.showInputDialog("Enter node name:");
if (newNodeName != null && !newNodeName.isEmpty()) {
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(newNodeName);
model.insertNodeInto(newNode, selectedNode, selectedNode.getChildCount());
// 展开父节点
tree.scrollPathToVisible(new TreePath(newNode.getPath()));
}
}
});
deleteButton.addActionListener(e -> {
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)
tree.getLastSelectedPathComponent();
if (selectedNode != null && !selectedNode.isRoot()) {
model.removeNodeFromParent(selectedNode);
}
});
// 创建窗口
JFrame frame = new JFrame("JTree Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(tree), BorderLayout.CENTER);
frame.add(buttonPanel, BorderLayout.SOUTH);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
// 自定义渲染器
static class CustomRenderer extends DefaultTreeCellRenderer {
@Override
public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
// 根据节点类型设置图标(这里简化处理)
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
if (leaf) {
setIcon(UIManager.getIcon("FileView.fileIcon"));
} else {
setIcon(expanded ?
UIManager.getIcon("FileView.directoryIcon") :
UIManager.getIcon("FileView.computerIcon"));
}
return this;
}
}
}
这个示例展示了 JTree 的基本用法,包括节点操作、事件监听和自定义渲染。你可以根据需要扩展功能,如添加右键菜单、拖拽支持等。