12.7Swing控件7 JTree

JTree 是 Swing 组件库中的树形结构组件,用于展示层级数据(如文件系统、组织结构图等)。

基本内容

  1. 节点(Node)

    • 树形结构的基本单元,分为叶节点(无子节点)和分支节点(有子节点)。
    • 常用实现类:DefaultMutableTreeNode
  2. 模型(TreeModel)

    • 管理节点的层级关系和数据。
    • 常用实现类:DefaultTreeModel
  3. 渲染器(TreeCellRenderer)

    • 自定义节点的显示样式(文本、图标、颜色等)。
  4. 监听器(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);

常见场景

  1. 文件浏览器
    使用 File 类构建文件系统树。
  2. 配置面板
    展示多级配置项。
  3. 组织结构图
    展示公司部门层级。

注意事项

  1. 性能优化

    • 大数据量时使用 TreeModel 的懒加载机制(如数据库分页查询)。
    • 使用 TreeWillExpandListener 控制节点展开逻辑。
  2. 线程安全

    • Swing 组件非线程安全,更新树结构需在事件调度线程(EDT)中进行:
      javax.swing.SwingUtilities.invokeLater(() -> {
          // 更新树模型的代码
      });
      

示例代码

下面是一个完整的 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 的基本用法,包括节点操作、事件监听和自定义渲染。你可以根据需要扩展功能,如添加右键菜单、拖拽支持等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chxii

小小打赏,大大鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值