7

我有一个具有大约 100000 个或更多节点的 JTree。现在我想扩展整棵树。为此,我使用我在这里找到的解决方案。

我的问题是扩展这么大的树需要 60 秒或更长时间,这不是很方便。有人对我如何加快扩展有任何建议吗?

4

6 回答 6

3

对于包含 150 000 个节点(具有超过 19 000 个可打开节点)的树,我遇到了同样的问题。我只是通过覆盖方法将扩展的持续时间除以 5 getExpandedDescendants

JTree tree = new javax.swing.JTree()
{
    @Override
    public Enumeration<TreePath> getExpandedDescendants(TreePath parent)
    {
        if (!isExpanded(parent))
        {
            return null;
        }
        return java.util.Collections.enumeration(getOpenedChild(parent, new javolution.util.FastList<TreePath>()));
    }

    /**
     * Search oppened childs recursively
     */
    private List<TreePath> getOpenedChild(TreePath paramTreeNode, List<TreePath> list)
    {
        final Object parent = paramTreeNode.getLastPathComponent();
        final javax.swing.tree.TreeModel model = getModel();
        int nbChild = model.getChildCount(parent);
        for (int i = 0; i < nbChild; i++)
        {
            Object child = model.getChild(parent, i);
            final TreePath childPath = paramTreeNode.pathByAddingChild(child);
            if (!model.isLeaf(child) && isExpanded(childPath))
            {
                //Add child if oppened
                list.add(childPath);
                getOpenedChild(childPath, list);
            }
        }
        return list;
    }
};

展开所有操作现在需要 5 秒而不是 25 秒,我仍在努力提高性能。

于 2013-10-25T09:16:32.733 回答
3

快捷方式:

JTree jTree;
for (int i = 0; i < jTree.getRowCount(); i++) {
         jTree.expandRow(i);
}
于 2014-03-28T10:25:32.490 回答
1

我尝试了解决方案,你也使用。

在我看来,那里提供的代码不是最优的: - 它为所有节点调用 tree.expandPath,而不是只为最深的非叶节点调用它(在叶节点上调用 expandPath 没有效果,请参阅 JDK)

这是一个应该更快的更正版本:

// If expand is true, expands all nodes in the tree.
    // Otherwise, collapses all nodes in the tree.
    public void expandAll(JTree tree, boolean expand) {
        TreeNode root = (TreeNode)tree.getModel().getRoot();
        if (root!=null) {   
            // Traverse tree from root
            expandAll(tree, new TreePath(root), expand);
        }
    }

    /**
     * @return Whether an expandPath was called for the last node in the parent path
     */
    private boolean expandAll(JTree tree, TreePath parent, boolean expand) {
        // Traverse children
        TreeNode node = (TreeNode)parent.getLastPathComponent();
        if (node.getChildCount() > 0) {
            boolean childExpandCalled = false;
            for (Enumeration e=node.children(); e.hasMoreElements(); ) {
                TreeNode n = (TreeNode)e.nextElement();
                TreePath path = parent.pathByAddingChild(n);
                childExpandCalled = expandAll(tree, path, expand) || childExpandCalled; // the OR order is important here, don't let childExpand first. func calls will be optimized out !
            }

            if (!childExpandCalled) { // only if one of the children hasn't called already expand
                // Expansion or collapse must be done bottom-up, BUT only for non-leaf nodes
                if (expand) {
                    tree.expandPath(parent);
                } else {
                    tree.collapsePath(parent);
                }
            }
            return true;
        } else {
            return false;
        }
    }
于 2010-10-15T21:20:00.607 回答
1

我认为您需要考虑一种显示策略,无论是广度优先(查看所有直系子代)还是深度优先(仅查看一个子代的所有后代)。100,000 个节点太多,无法在屏幕上查看,您需要考虑平移和缩放。您应该考虑可以选择所需后代子集的过滤器。

一种策略可能是显示最上面的孩子,当你的鼠标进入一个孩子时,显示它的所有后代,当你离开时折叠它们。通过这种方式,您可以浏览显示当前感兴趣的子树的树。

于 2009-12-15T12:50:00.050 回答
1

我在以下模式上取得了一些成功:

tree = new JTree(...)
tree.setLargeModel(true);

这已经使一些大型扩展(150,000 个树节点)从 12 秒 -> 3.5 秒

然后以更快的速度批量扩展:

TreeUI treeUI = tree.getUI();
tree.setUI(null);
try {
  // perform bulk expansion logic, like in other answers
} finally {
  tree.setUI(treeUI);
}

这使它下降到大约 1.0 秒。

于 2016-09-09T21:29:11.587 回答
0

是的,重新考虑你的 UI 元素。JTree 不是您要显示的 100,000 个节点。使用可以看到表格的东西并单击项目以深入查看表格元素。然后有一个类似历史的面包屑,以便用户可以向上导航层次结构..

如果您坚持拥有一个 JTree,有一种方法可以接管它们重新绘制的方式,但我不知道这是否会帮助您解决扩展问题。

于 2009-12-15T13:20:30.160 回答