JTree树形数据展示操作

wen java案例 2

本文目录导读:

JTree树形数据展示操作

  1. 基础树形结构创建
  2. 动态添加节点
  3. 节点事件处理
  4. 自定义节点渲染
  5. 搜索和过滤
  6. 拖拽操作
  7. 完整示例:文件浏览器
  8. 性能优化技巧

我来详细介绍JTree树形数据展示的各种操作:

基础树形结构创建

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
public class TreeExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("JTree示例");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        // 创建根节点
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("根节点");
        // 创建子节点
        DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("节点1");
        DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("节点2");
        DefaultMutableTreeNode node3 = new DefaultMutableTreeNode("节点3");
        // 创建叶子节点
        DefaultMutableTreeNode leaf1 = new DefaultMutableTreeNode("叶子1");
        DefaultMutableTreeNode leaf2 = new DefaultMutableTreeNode("叶子2");
        // 构建树
        root.add(node1);
        root.add(node2);
        root.add(node3);
        node1.add(leaf1);
        node1.add(leaf2);
        // 创建JTree
        JTree tree = new JTree(root);
        frame.add(new JScrollPane(tree));
        frame.setVisible(true);
    }
}

动态添加节点

public class DynamicTreeExample {
    private DefaultMutableTreeNode selectedNode;
    private DefaultTreeModel model;
    // 添加子节点
    public void addChildNode(String nodeName) {
        if (selectedNode != null) {
            DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(nodeName);
            model.insertNodeInto(newNode, selectedNode, selectedNode.getChildCount());
            // 展开新节点
            tree.scrollPathToVisible(new TreePath(newNode.getPath()));
        }
    }
    // 删除节点
    public void removeSelectedNode() {
        if (selectedNode != null && selectedNode.getParent() != null) {
            model.removeNodeFromParent(selectedNode);
        }
    }
    // 添加根节点
    public void addRootNode(String rootName) {
        DefaultMutableTreeNode newRoot = new DefaultMutableTreeNode(rootName);
        model.setRoot(newRoot);
        tree.expandPath(new TreePath(newRoot.getPath()));
    }
}

节点事件处理

public class TreeEventListener {
    // 节点选择事件
    public void setupNodeSelectionListener(JTree tree) {
        tree.addTreeSelectionListener(e -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) 
                tree.getLastSelectedPathComponent();
            if (selectedNode != null) {
                System.out.println("选中节点: " + selectedNode.getUserObject());
                System.out.println("层级: " + selectedNode.getLevel());
                System.out.println("是否是叶子节点: " + selectedNode.isLeaf());
            }
        });
    }
    // 节点展开/折叠事件
    public void setupExpandCollapseListener(JTree tree) {
        tree.addTreeExpansionListener(new TreeExpansionListener() {
            @Override
            public void treeExpanded(TreeExpansionEvent event) {
                TreePath path = event.getPath();
                System.out.println("展开节点: " + path.getLastPathComponent());
            }
            @Override
            public void treeCollapsed(TreeExpansionEvent event) {
                TreePath path = event.getPath();
                System.out.println("折叠节点: " + path.getLastPathComponent());
            }
        });
    }
}

自定义节点渲染

public class CustomTreeCellRenderer extends DefaultTreeCellRenderer {
    @Override
    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;
        // 自定义图标
        if (node.isLeaf()) {
            setIcon(new ImageIcon("leaf_icon.png"));
        } else if (expanded) {
            setIcon(new ImageIcon("expanded_icon.png"));
        } else {
            setIcon(new ImageIcon("collapsed_icon.png"));
        }
        // 自定义颜色
        if (node.getLevel() == 0) {
            setForeground(Color.RED);
        } else if (node.getLevel() == 1) {
            setForeground(Color.BLUE);
        }
        // 自定义字体
        if (node.getLevel() == 0) {
            setFont(getFont().deriveFont(Font.BOLD, 14));
        }
        return this;
    }
}

搜索和过滤

public class TreeSearchFilter {
    // 搜索节点
    public List<TreePath> searchNodes(DefaultMutableTreeNode root, String searchText) {
        List<TreePath> result = new ArrayList<>();
        if (searchText == null || searchText.isEmpty()) {
            return result;
        }
        searchNodesRecursive(root, new TreePath(root), searchText.toLowerCase(), result);
        return result;
    }
    private void searchNodesRecursive(DefaultMutableTreeNode node, 
            TreePath path, String searchText, List<TreePath> result) {
        String nodeText = node.getUserObject().toString().toLowerCase();
        if (nodeText.contains(searchText)) {
            result.add(path);
        }
        for (int i = 0; i < node.getChildCount(); i++) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
            searchNodesRecursive(child, path.pathByAddingChild(child), searchText, result);
        }
    }
    // 节点过滤(只显示匹配的节点)
    public void filterTree(JTree tree, String filter) {
        DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
        filterNode(root, filter.toLowerCase());
        model.reload();
        expandAllNodes(tree);
    }
    private boolean filterNode(DefaultMutableTreeNode node, String filter) {
        boolean matches = node.getUserObject().toString().toLowerCase().contains(filter);
        // 递归检查子节点
        for (int i = node.getChildCount() - 1; i >= 0; i--) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
            boolean childMatches = filterNode(child, filter);
            if (!childMatches) {
                node.remove(i);
            }
            matches = matches || childMatches;
        }
        return matches;
    }
}

拖拽操作

public class DragDropTreeExample {
    public void enableDragDrop(JTree tree) {
        // 启用拖拽
        tree.setDragEnabled(true);
        tree.setTransferHandler(new TreeTransferHandler());
        // 设置拖拽模式
        tree.getDropTarget().setDefaultActions(DnDConstants.MOVE);
    }
    // 自定义TransferHandler
    class TreeTransferHandler extends TransferHandler {
        private DataTransferNode[] nodes = null;
        @Override
        public int getSourceActions(JComponent c) {
            return TransferHandler.COPY_OR_MOVE;
        }
        @Override
        protected Transferable createTransferable(JComponent c) {
            JTree tree = (JTree) c;
            TreePath[] paths = tree.getSelectionPaths();
            if (paths != null) {
                nodes = new DataTransferNode[paths.length];
                for (int i = 0; i < paths.length; i++) {
                    DefaultMutableTreeNode node = 
                        (DefaultMutableTreeNode) paths[i].getLastPathComponent();
                    nodes[i] = new DataTransferNode(node);
                }
            }
            return new DataTransferable(nodes);
        }
        @Override
        public boolean canImport(TransferSupport support) {
            return support.isDataFlavorSupported(DataFlavor.stringFlavor);
        }
        @Override
        public boolean importData(TransferSupport support) {
            // 实现导入逻辑
            return true;
        }
    }
}

完整示例:文件浏览器

public class FileTreeBrowser extends JPanel {
    private JTree tree;
    private DefaultTreeModel model;
    private DefaultMutableTreeNode root;
    public FileTreeBrowser() {
        setLayout(new BorderLayout());
        // 创建根节点
        root = new DefaultMutableTreeNode("我的电脑");
        model = new DefaultTreeModel(root);
        tree = new JTree(model);
        // 添加系统根目录
        File[] roots = File.listRoots();
        for (File rootFile : roots) {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode(rootFile);
            root.add(node);
            // 预加载子文件
            addDummyChildren(node);
        }
        // 设置渲染器
        tree.setCellRenderer(new FileTreeCellRenderer());
        // 添加展开事件
        tree.addTreeWillExpandListener(new TreeWillExpandListener() {
            @Override
            public void treeWillExpand(TreeExpansionEvent event) 
                    throws ExpandVetoException {
                TreePath path = event.getPath();
                DefaultMutableTreeNode node = 
                    (DefaultMutableTreeNode) path.getLastPathComponent();
                // 动态加载子文件
                if (node.getChildCount() == 1 && 
                    node.getChildAt(0).toString().equals("加载中...")) {
                    node.removeAllChildren();
                    loadChildren(node);
                }
            }
            @Override
            public void treeWillCollapse(TreeExpansionEvent event) 
                    throws ExpandVetoException {
                // 允许折叠
            }
        });
        add(new JScrollPane(tree), BorderLayout.CENTER);
    }
    private void addDummyChildren(DefaultMutableTreeNode node) {
        node.add(new DefaultMutableTreeNode("加载中..."));
    }
    private void loadChildren(DefaultMutableTreeNode node) {
        File file = (File) node.getUserObject();
        File[] files = file.listFiles();
        if (files != null) {
            for (File child : files) {
                DefaultMutableTreeNode childNode = 
                    new DefaultMutableTreeNode(child);
                node.add(childNode);
                // 如果是目录,添加占位节点
                if (child.isDirectory()) {
                    addDummyChildren(childNode);
                }
            }
        }
        model.reload(node);
    }
    // 文件树渲染器
    class FileTreeCellRenderer extends DefaultTreeCellRenderer {
        @Override
        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;
            Object userObject = node.getUserObject();
            if (userObject instanceof File) {
                File file = (File) userObject;
                setText(file.getName().isEmpty() ? file.getPath() : file.getName());
                // 设置图标
                if (file.isDirectory()) {
                    setIcon(UIManager.getIcon("FileView.directoryIcon"));
                } else {
                    setIcon(UIManager.getIcon("FileView.fileIcon"));
                }
            }
            return this;
        }
    }
}

性能优化技巧

public class TreePerformanceOptimization {
    // 延迟加载
    public void lazyLoadChildren(DefaultMutableTreeNode node) {
        // 只在节点展开时才加载子节点
        if (node.getAllowsChildren() && node.getChildCount() == 0) {
            loadChildNodesAsync(node);
        }
    }
    // 异步加载
    private void loadChildNodesAsync(DefaultMutableTreeNode node) {
        SwingWorker<Void, DefaultMutableTreeNode> worker = 
            new SwingWorker<Void, DefaultMutableTreeNode>() {
            @Override
            protected Void doInBackground() throws Exception {
                // 模拟耗时操作
                Thread.sleep(100);
                // 批量添加子节点
                for (int i = 0; i < 100; i++) {
                    DefaultMutableTreeNode child = 
                        new DefaultMutableTreeNode("子节点 " + i);
                    publish(child);
                }
                return null;
            }
            @Override
            protected void process(List<DefaultMutableTreeNode> chunks) {
                for (DefaultMutableTreeNode child : chunks) {
                    node.add(child);
                }
                model.reload(node);
            }
        };
        worker.execute();
    }
    // 批量更新
    public void batchUpdate(DefaultTreeModel model, 
            DefaultMutableTreeNode parent, List<String> newChildren) {
        // 暂时关闭监听器
        model.removeTreeModelListener(model.getTreeModelListeners()[0]);
        // 批量操作
        for (String childName : newChildren) {
            DefaultMutableTreeNode child = new DefaultMutableTreeNode(childName);
            model.insertNodeInto(child, parent, parent.getChildCount());
        }
        // 重新启用监听器并刷新
        model.addTreeModelListener(new DefaultTreeModelListener());
        model.reload();
    }
}

这些示例涵盖了JTree的常见操作,你可以根据实际需求选择合适的实现方式,记住要处理好线程安全问题,特别是在Swing事件线程中进行更新操作。

抱歉,评论功能暂时关闭!