设置新 TreeModel 时如何自动扩展 JTree?

Posted

技术标签:

【中文标题】设置新 TreeModel 时如何自动扩展 JTree?【英文标题】:How do I auto-expand a JTree when setting a new TreeModel? 【发布时间】:2013-02-19 02:20:01 【问题描述】:

我有一个自定义的JTree 和一个自定义的JModel;当我给它一个新模型时,我希望 JTree “自动扩展”。目前,它只是简单地将所有节点折叠到根。

这是一个例子:

private class CustomTree extends JTree 

    @Override
    public boolean isExpanded(TreePath path) 
        return ((Person) path.getLastPathComponent).hasChildren();



private class CustomTreeModel extends TreeModel 

    // ... omitting various implementation details

    @Override
    public boolean isLeaf(Object object) 
        return !((Person) object).hasChildren();
    



Model model = new Model();
Person bob = new Person();
Person alice = new Person();
bob.addChild(alice);
model.setRoot(bob);
JTree tree = new CustomTree(new CustomTreeModel(model));

此时,树正确显示:

- BOB
  - ALICE

其中 Alice 是 Bob 的孩子(在数据和可视化树中)

但是,如果我打电话:

tree.setModel(new CustomTreeModel(model));

一切都折叠起来了:

+ BOB

有没有办法在设置新模型时“自动展开”树中的所有内容?

【问题讨论】:

此代码和描述中没有任何想法,模型更改后所有通知器和侦听器都会消失, @mKorbel 我相信我下面的回答可以解决我的问题。 :-) ............. 不要使用 int 索引,您可能会丢失此索引,必须存储有关节点公司的所有可访问信息。对象值(我的观点) 扩展设置新模型。为了尽快获得更好的帮助,请发帖SSCCE。 @mKorbel 对不起,我不太明白 - 我可以失去 tree.getRowCount() 索引吗?怎么样? 【参考方案1】:

以下对我有用(在设置新模型后调用):

for (int i = 0; i < tree.getRowCount(); i++) 
    tree.expandRow(i);

【讨论】:

@all:这个方案就够了,这里不需要递归 至于“为什么”:因为expandRow() 会显示更多行,所以getRowCount() 在每次展开后都会增加。试图通过存储n = getRowCount()for (i=0; i&lt;n; i++) 变得聪明是行不通的。【参考方案2】:

我也遇到过类似的问题。

您的解决方案(如 https://***.com/a/15211697/837530 发布的那样)似乎仅适用于***树节点。

但我需要展开所有的后代节点。于是我用下面的递归方法解决了:

private void expandAllNodes(JTree tree, int startingIndex, int rowCount)
    for(int i=startingIndex;i<rowCount;++i)
        tree.expandRow(i);
    

    if(tree.getRowCount()!=rowCount)
        expandAllNodes(tree, rowCount, tree.getRowCount());
    

被调用

expandAllNodes(tree, 0, tree.getRowCount());

其中,treeJTree

除非有人有更好的解决方案。

【讨论】:

请参阅下面的 sdasdadas 答案,了解没有递归的 3 行解决方案。 您正在保存 rowCount,然后展开那么多行。但是当您扩展它们时,会添加更多行。如果您将for 语句中的i&lt;rowCount 更改为i&lt;tree.getRowCount(),它将继续从顶部扩展,并且在到达所有扩展行之前不会结束,无需递归。【参考方案3】:

还有这个非递归版本。

private void expandAllNodes(JTree tree) 
    int j = tree.getRowCount();
    int i = 0;
    while(i < j) 
        tree.expandRow(i);
        i += 1;
        j = tree.getRowCount();
    

【讨论】:

【参考方案4】:

这对我有用..

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Enumeration;

public class JTreeNodeAutoExpandCollapse extends JFrame 
    public JTreeNodeAutoExpandCollapse() throws HeadlessException 
        initializeUI();
    

    private void initializeUI() 
        setSize(200, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
        DefaultMutableTreeNode chapter1 = new DefaultMutableTreeNode("Chapter 1");
        DefaultMutableTreeNode sub1 = new DefaultMutableTreeNode("1.1");
        DefaultMutableTreeNode sub2 = new DefaultMutableTreeNode("1.2");
        DefaultMutableTreeNode sub3 = new DefaultMutableTreeNode("1.3");
        DefaultMutableTreeNode sub31 = new DefaultMutableTreeNode("1.3.1");
        DefaultMutableTreeNode sub32 = new DefaultMutableTreeNode("1.3.2");

        root.add(chapter1);
        chapter1.add(sub1);
        chapter1.add(sub2);
        chapter1.add(sub3);
        sub3.add(sub31);
        sub3.add(sub32);

        final JTree tree = new JTree(root);
        expandTree(tree, false);

        JScrollPane pane = new JScrollPane(tree);
        pane.setPreferredSize(new Dimension(200, 200));

        JPanel buttonPanel = new JPanel(new BorderLayout());
        JButton expandAll = new JButton("Expand All");
        expandAll.addActionListener(new ActionListener() 
            public void actionPerformed(ActionEvent e) 
                expandTree(tree, true);
            
        );

        JButton collapseAll = new JButton("Collapse All");
        collapseAll.addActionListener(new ActionListener() 
            public void actionPerformed(ActionEvent e) 
                expandTree(tree, false);
            
        );

        buttonPanel.add(expandAll, BorderLayout.WEST);
        buttonPanel.add(collapseAll, BorderLayout.EAST);

        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(pane, BorderLayout.CENTER);
        getContentPane().add(buttonPanel, BorderLayout.SOUTH);
    

    private void expandTree(JTree tree, boolean expand) 
        TreeNode root = (TreeNode) tree.getModel().getRoot();
        expandAll(tree, new TreePath(root), expand);
    

    private void expandAll(JTree tree, TreePath path, boolean expand) 
        TreeNode node = (TreeNode) path.getLastPathComponent();

        if (node.getChildCount() >= 0) 
            Enumeration enumeration = node.children();
            while (enumeration.hasMoreElements()) 
                TreeNode n = (TreeNode) enumeration.nextElement();
                TreePath p = path.pathByAddingChild(n);

                expandAll(tree, p, expand);
            
        

        if (expand) 
            tree.expandPath(path);
         else 
            tree.collapsePath(path);
        
    

    public static void main(String[] args) 
        SwingUtilities.invokeLater(new Runnable() 
            public void run() 
                new JTreeNodeAutoExpandCollapse().setVisible(true);
            
        );
    

【讨论】:

【参考方案5】:
public void expandTree()
    int row = 1;
    while (row++ < tree.getRowCount())
        tree.expandRow(row);
    

public void collapseTree()
    int row = tree.getRowCount() - 1;
    while (row-- > 0)
        tree.collapseRow(row);
    

【讨论】:

请在您的代码中添加一些解释。此外,由于这是一个老问题,请检查您的答案是否已包含在另一个答案中。 @Alexander,在 expandTree() 方法中 int row = 1;应该从 0(int row = 0;) 开始,否则 Root 节点之后的第一个节点不会展开。

以上是关于设置新 TreeModel 时如何自动扩展 JTree?的主要内容,如果未能解决你的问题,请参考以下文章

John the Ripper (“JtR”)密码破解工具

在自动扩展组中的 EC2 启动和关闭时运行命令

Gtkmm ListStore,如何在其中一行中捕获该值已更改?

如何让outlook自动提示收到新邮件

如何关闭 Apple Watch 扩展的自动安装?

(保存对话框)如何在 Vista/Win7 中更改文件过滤器时自动更改文件扩展名?