Hiding/filtering nodes in a JTree?

Amanda S picture Amanda S · May 6, 2009 · Viewed 15.6k times · Source

I have a data object represented in a TreeModel, and I'd like to show only part of it in my JTree--for the sake of argument, say the leaves and their parents. How can I hide/filter the unnecessary nodes?

Answer

Amanda S picture Amanda S · May 7, 2009

My eventual implementation:

  • Have two TreeModels, the underlying one and the filtered one.
  • When a change occurs on the underlying TreeModel, rebuild the filtered TreeModel from scratch. Clone each node that should be visible, and add it to its first visible ancestor in the filtered TreeModel (or the root if none are visible). See teh codez below, if you're curious.
  • This has the unfortunate side effect of collapsing every path the user had open. To get around this, I added a TreeModelListener to the filtered TreeModel. When the model changes, I save the expanded paths in the JTree (using getExpandedDescendants()), then re-expand them later (using SwingUtilities.invokeLater()).

    I had to override equals() in the TreeNode class I was using so that the new cloned nodes would be the same as the old cloned nodes.


  ...
  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);
      }
    }
  }