我使用View过滤方法成功过滤了一个JTree(在树渲染中,为过滤掉的项目将首选组件大小设置为0)。请参阅[Filtering on a JTree
我有一个包含超过100万个树项目的扩展环境。
问题是当一些树项被过滤掉时,性能会大大降低(扩展树,滚动非常慢)。
我的代码如下:
public static class TreeRenderer extends DefaultTreeCellRenderer
{
@Override
public Component getTreeCellRendererComponent( final JTree tree, final Object value, final boolean selected,
final boolean expanded, final boolean leaf, final int row, final boolean hasFocus )
{
// Invoke default Implementation, setting all values of this
super.getTreeCellRendererComponent( tree, value, selected, expanded, leaf, row, hasFocus );
if( !isNodeVisible( (DefaultMutableTreeNode)value ) )
{
setPreferredSize( new Dimension( 0, 0 ) );
}
else
{
setPreferredSize( new Dimension( 200, 15 ) );
}
return this;
}
}
public static boolean isNodeVisible( final DefaultMutableTreeNode value )
{
// In this example all Nodes without a UserObject are invisible
return value.getUserObject() != null;
}
如果我将setPreferredSize(new Dimension(0,0))的值(宽度,高度)更改为0以外的值,则性能会增加到正常。
在Jtree中设置零大小的组件有什么用?我错过了什么?我是否可以使用View方法对其进行排序?
由于
答案 0 :(得分:1)
这是一个有趣的。不幸的是,我无法提供解决方案,但至少认为找到了性能下降的原因。
我开始调查这个问题,这是由JTree#setRowHeight(int)
方法评论引起的直觉导致的。特别是,我寻找高度为0的地方可能具有类似的特殊含义,并导致不希望的计算。
我发现我认为是性能问题的实际原因。这导致了一些通常不关心的(非公开)类,但最终,性能问题似乎是由javax.swing.tree.VariableHeightLayoutCache.TreeStateNode#hasValidSize()
方法引起的:
/*
* Returns true if this node has a valid size.
*/
public boolean hasValidSize() {
return (preferredHeight != 0);
}
此方法用于确定是否必须更新某个组件状态。当首选大小为0时,此方法“验证”节点状态 - 再次导致优选高度0,这被认为是“无效”。这导致许多重复更新,每次更新都涉及对单元格渲染器的getTreeCellRendererComponent
方法的调用,因此对于具有1百万个节点的树,调用数百万次(与少数节点相比)当首选高度不 0时,总共有几千个电话。
对不起,我知道,这对你没什么帮助。相应的类不是公共的,创建自己的实现意味着构建一些相当大的基础结构(可能具有自己的布局缓存和自己的树UI ...)。
我不确定基于模型的过滤是否对您来说是一个可行的选择 - 特别是因为我知道这也不是一件容易的事,除非有人创建一个全新的树模型,在处理数百万个节点时,这可能不是最好的想法...
然而,也许这种见解可以帮助其他人找到解决方案。任何找到合适解决方案的人(或view-based filtering on JTrees in general)都会从我那里获得 +1 (可能还有一些赏金)。这里的“好”解决方案意味着它不应该涉及任何黑客攻击。特别是,上述问题中的当前解决方案是“黑客攻击”,因为它们会导致不良行为(例如,当使用键盘导航树时,仍会遍历隐藏节点)。