2013-03-04 52 views
10

我有一个自定义JTree和一个自定义JModel;当我给它一个新的模型时,我会让JTree“自动扩展”。目前,它只是将所有节点折叠到根目录。如何在设置新的TreeModel时自动扩展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 

爱丽丝是Bob的孩子(无论是在数据和在视觉树)

但是,如果我叫:

tree.setModel(new CustomTreeModel(model)); 

一切都崩溃了:

+ BOB 

有没有办法设置一个新的模型时,“自动扩展”树一切?

+0

没有从这个代码和说明思路,模式改变之后,所有通告和听众走开, – mKorbel 2013-03-04 21:39:10

+0

@mKorbel我相信我的回答如下解决了我问题。 – sdasdadas 2013-03-04 21:43:12

+0

:-) ...............不要使用int的索引,你可能会丢失这个索引,必须存储关于节点inc的所有可访问信息。对象值(我的视图) – mKorbel 2013-03-04 21:47:07

回答

13

我也有类似的问题。

您的解决方案(如发布https://stackoverflow.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

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

+0

这只适用于前3级:/ – mattymanme 2016-05-17 13:26:00

22

以下为我工作(设置新模式之后调用):

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

@all:这个解决方案是足够的,这里不需要递归 – ferkulat 2015-05-23 13:05:10

+5

至于“为什么”:它的工作原理是因为'expandRow()'将显示更多行,使得在每次展开后增加'getRowCount()'。试图通过存储'n = getRowCount()'和'for(i = 0; i Matthieu 2016-09-09 12:57:00

8

还有这个非递归版本。

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

因为我可以编辑,也没有评论公认的答案既不回答OP的最后一个问题:

有没有办法设置一个新的模型时,“自动扩展”树中的一切?

要展开树的新模式分配后(由OP的要求),在自定义树覆盖treeDidChange()

@Override 
public void treeDidChange() { 
    super.treeDidChange(); 
    expandAllNodes(this, 0, getRowCount()); 
} 
1

这个工作对我来说..

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); 
      } 
     }); 
    } 
}