我已经使用“视图过滤”方法成功过滤了JTree(在树渲染中,将过滤出的项目的首选组件大小设置为0)。请参阅[Filtering on a JTree
我有一个超过一百万个树项目的扩展环境。
问题在于,当某些树项被过滤掉时,性能会大大降低(树扩展,滚动非常慢)。
我的代码如下:
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方法解决这个问题?
谢谢
最佳答案
真有趣。不幸的是,我无法提供解决方案,但至少认为已经找到了性能下降的原因。
我开始对此进行调查,这是由于方法注释(如 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
方法的调用,因此,对于具有100万个节点的树,该方法被调用了数百万次(相比之下,当首选高度为不为0)。抱歉,我知道,这对您没有太大帮助。各自的类不是公共的,并且创建自己的实现将意味着构建一些重要的基础结构(可能具有自己的布局缓存和自己的Tree UI ...)。
我不确定基于模型的过滤是否对您来说是一个可行的选择-尤其是因为我知道这也不是小事,除非有人创建了一个全新的树模型,这反过来可能不是处理这个问题的最佳方法数百万个节点...
但是,也许这种见解可以帮助其他人找到解决方案。任何为此(或view-based filtering on JTrees in general)找到好的解决方案的人都会收到我的 +1 (也许还有一些赏金)。这里的“好”解决方案意味着它不应涉及任何黑客行为。特别是,上述问题中的当前解决方案是“hacks”,因为它们会导致不良行为(例如,当使用键盘在树中导航时,仍会遍历隐藏的节点)。