我有一个大约有100000个或更多节点的JTree。现在我想扩展整棵树。为此,我使用了我找到的解决方案here。
我的问题是扩展这么大的树需要60秒或更长时间,这不是很方便。有没有人有任何建议我如何加快扩张?
答案 0 :(得分:3)
快捷方式:
JTree jTree;
for (int i = 0; i < jTree.getRowCount(); i++) {
jTree.expandRow(i);
}
答案 1 :(得分:2)
我遇到了一个包含150 000个节点(超过19 000个可打开节点)的树的问题。我只是通过覆盖方法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秒,我仍在努力提高性能。
答案 2 :(得分:1)
我认为你需要考虑一种展示策略,无论是广度优先(看看所有直接的孩子)还是深度优先(看看一个孩子的所有后代)。 100,000是要在屏幕上查看的节点太多,您需要考虑平移和缩放。您应该考虑可以选择所需后代子集的过滤器。
一种策略可能是显示顶级儿童,当您的鼠标进入儿童时,显示其所有后代以及何时离开它们。通过这种方式,您可以在显示当前感兴趣的子树的树上导航。
答案 3 :(得分: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;
}
}
答案 4 :(得分:0)
是的,重新考虑你的UI元素。 JTree不是您要显示的100,000个节点。使用可以查看表格的内容,然后单击项目以深入查看表格元素。然后有一个像历史一样的面包屑,以便用户可以向上导航层次结构..
如果你坚持使用JTree,有一种方法可以接管它重绘的方式,但我不知道这是否会帮助你解决扩展问题。
答案 5 :(得分:0)
我使用以下模式取得了一些成功:
tree = new JTree(...)
tree.setLargeModel(true);
这已经从12s带来了一些大的扩展(150,000个树节点) - &gt; 3.5s的
然后更快地扩大批量:
TreeUI treeUI = tree.getUI();
tree.setUI(null);
try {
// perform bulk expansion logic, like in other answers
} finally {
tree.setUI(treeUI);
}
这使其降至约1.0秒。