在 JTree 中隐藏/过滤节点?

Posted

技术标签:

【中文标题】在 JTree 中隐藏/过滤节点?【英文标题】:Hiding/filtering nodes in a JTree? 【发布时间】:2010-10-24 07:50:54 【问题描述】:

我有一个用TreeModel 表示的数据对象,我想在我的JTree 中只显示它的一部分——为了争论,说树叶和他们的父母。如何隐藏/过滤不必要的节点?

【问题讨论】:

这是一个过时且信息量较少的线程,而不是此副本:***.com/questions/9234297/filtering-on-a-jtree 【参考方案1】:

我的最终实现:

有两个TreeModels,一个是底层的,一个是过滤的。 当底层TreeModel 发生更改时,从头开始重建过滤的TreeModel。克隆每个应该可见的节点,并将其添加到过滤后的TreeModel 中的第一个可见祖先(如果不可见,则添加到根)。如果您好奇,请参阅下面的 codez。

这有一个不幸的副作用,就是折叠用户打开的每条路径。为了解决这个问题,我在过滤后的TreeModel 中添加了一个TreeModelListener。当模型发生变化时,我将展开的路径保存在JTree(使用getExpandedDescendants())中,然后稍后重新展开(使用SwingUtilities.invokeLater())。

我必须在我正在使用的TreeNode 类中覆盖equals(),以便新的克隆节点与旧的克隆节点相同。


  ...
  populateFilteredNode(unfilteredRoot, filteredRoot);
  ...

  void populateFilteredNode(TreeNode unfilteredNode, TreeNode filteredNode)
  
    for (int i = 0; i < unfilteredNode.getChildCount(); i++)
    
      TreeNode unfilteredChildNode = unfilteredNode.getChildAt(i);

      if (unfilteredChildNode.getType() == Type.INVISIBLE_FOLDER)
      
        populateFilteredNode(unfilteredChildNode, filteredNode);
      
      else
      
        TreeNode filteredChildNode = unfilteredChildNode.clone();

        filteredNode.add(filteredChildNode);

        populateFilteredNode(unfilteredChildNode, filteredChildNode);
      
    
  

【讨论】:

【参考方案2】:

您应该知道GlazedLists。这是一个很棒的库,可以轻松进行复杂的表转换。它们也扩展到树木。可能需要对现有代码进行一些重构才能使其进入 GlazedLists 的工作方式。但请查看演示和网络广播,了解它的强大功能。 (在我看来,它是必不可少的 Swing 库之一,而且它是开源的。)

【讨论】:

我在 GlazedLists 中看不到任何树木:java.net/projects/glazedlists/sources/svn/show/trunk/source/ca/… 请您告诉我们您在哪里找到了它的树木过滤 API? @gouessej 它在扩展文件夹中:java.net/projects/glazedlists/sources/svn/show/trunk/extensions/…【参考方案3】:

你试过JXTree 吗? (不幸的是,该网站现在已关闭,但您可以谷歌寻找镜像)

【讨论】:

其实JXTree中过滤器的支持即使是计划好的也从来没有实现过,我只是在它的源代码中看到了一个关于过滤的受保护的未使用字段。【参考方案4】:

看看这个实现:http://www.java2s.com/Code/Java/Swing-Components/InvisibleNodeTreeExample.htm

它创建 DefaultMutableNode 的子类,添加一个“isVisible”属性,而不是实际从 TreeModel 中删除/添加节点。

【讨论】:

我最近需要在 JTree 中实现过滤,这个解决方案是迄今为止最干净和最简单的。【参考方案5】:

如果您正在寻找商业解决方案,JideSoft 有一个可过滤的树模型。除此之外,SwingX 有一个过滤器 API,可用于 JXTable、JXTreeTable、JXTree 和 JXList。

【讨论】:

谢谢!我尝试了 Jide 之一,但我无法让它做我想做的事。有机会我会研究 SwingX API。 你到底想做什么?如果您提供详细信息,我也许可以提供一些特定的代码。据我了解,将显示搜索条件中过滤的叶子及其父母。这显示在他们的 webstart 演示中,jidesoft.com/products/download.htm,“所有 JIDE 产品的演示”。在此,查看 QuickFilter (Tree) Demo。 我记得,我很难让 Jide 树模型显示隐形父母的可见孩子。 我无法关注你。能详细解释一下吗? 阿曼达 S,你的意思是你的过滤器表明父母应该被隐藏,除非他们的至少一个孩子是可见的?这种情况由这段代码处理:adrianwalker.org/2012/04/filtered-jtree.html【参考方案6】:

只要它仍然是您正在显示的树,那么过滤您现有的TreeModelTreeModel 应该足够简单。

【讨论】:

你能进一步解释一下吗? 你想知道什么。您会发现更容易找到对 TableModel 执行相同操作的示例。您想创建一个委托给当前模型的 TreeModel,但删除您不想出现的节点。我建议,至少在开始时,您将所有事件作为 structureChanged 传播(尽管想想这会导致树扩展崩溃)。 部分问题是“删除我不想出现的节点”也会删除它们的子节点,即使我可能想显示它们。 你需要一些父母。 JTree(更重要的是 PL&F)没有办法用省略的父母来表示孩子。如果您想要改变树的绘制方式,您需要了解特定 PL&F 实现。 我可以将节点添加到“可见”祖先(或根,如果所有节点的祖先都被隐藏),但如果我取消隐藏中间的任何节点,这会很痛苦。 【参考方案7】:

利用您用于构建 TreeNode 的代码并重建 TreeNode(仅包括您想要的元素)。用过滤后的根节点设置 TreeModel 上的根节点。

【讨论】:

这是可行的,但是当你设置另一个模型时,JTree 会在后台做很多事情,尤其是当它检测到结构变化时。它在性能方面不是很好,无论是速度还是内存占用。

以上是关于在 JTree 中隐藏/过滤节点?的主要内容,如果未能解决你的问题,请参考以下文章

如何在jtree中仅列出非隐藏和非系统文件

java中jtree双击叶节点如何获取该文件所在的路径

过滤 JTree [关闭]

在 JTree 中拖放节点

如何在 Odoo 14 中隐藏过滤器

java jtree在延迟后重新显示每个项目的工具提示