Filtering on a JTree

Robin picture Robin · Feb 10, 2012 · Viewed 15.8k times · Source

Problem

Applying filtering on a JTree to avoid certain nodes/leaves to show up in the rendered version of the JTree. Ideally I am looking for a solution which allows to have a dynamic filter, but I would already be glad if I can get a static filter to work.

To make it a bit easier, let us suppose the JTree only supports rendering, and not editing. Moving, adding, removing of nodes should be possible.

An example is a search field above a JTree, and on typing the JTree would only show the subtree with matches.

A few restrictions: it is to be used in a project which has access to JDK and SwingX. I would like to avoid to include other third party libs.

I already thought of a few possible solutions, but neither of those seemed ideal

Approaches

Model based filtering

  • decorate the TreeModel to filter out some of the values. A quick-and-dirt version is easy to write. Filter out nodes, and on every change of the filter or the delegate TreeModel the decorator can fire an event that the whole tree has changes (treeStructureChanged with the root node as node). Combine this with listeners which restore the selection state and the expansion state of the JTree and you get a version which works more or less, but the events originating from the TreeModel are messed up. This is more or less the approach used in this question
  • decorate the TreeModel but try fire the correct events. I did not (yet) managed to come up with a working version of this. It seems to require a copy of the delegate TreeModel in order to be able to fire an event with the correct child indices when nodes are removed from the delegate model. I think with some more time I could get this to work, but it just feels wrong (filtering feels like something the view should do, and not the model)
  • decorate whatever data structure was used to create the initial TreeModel. However, this is completely non-reusable, and probably as hard as to write a decorator for a TreeModel

View based filtering

This seems like the way to go. Filtering should not affect the model but only the view.

  • I took a look at RowFilter class. Although the javadoc seems to suggest you can use it in combination with a JTree:

    when associated with a JTree, an entry corresponds to a node.

    I could not find any link between RowFilter (or RowSorter) and the JTree class. The standard implementations of RowFilter and the Swing tutorials seems to suggest that RowFilter can only be used directly with a JTable (see JTable#setRowSorter). No similar methods are available on a JTree

  • I also looked at the JXTree javadoc. It has a ComponentAdapter available and the javadoc of ComponentAdapter indicates a RowFilter could interact with the target component, but I fail to see how I make the link between the RowFilter and the JTree
  • I did not yet look at how a JTable handles the filtering with RowFilters, and perhaps the same can be done on a modified version of a JTree.

So in short: I have no clue on what's the best approach to solve this

Note: this question is a possible duplicate of this question, but that question is still unanswered, the question rather short and the answers seems incomplete, so I thought to post a new question. If this is not done (the FAQ did not provide a clear answer on this) I will update that 3year old question

Answer

Martin Wickman picture Martin Wickman · Dec 14, 2012

Take a look at this implementation: http://www.java2s.com/Code/Java/Swing-Components/InvisibleNodeTreeExample.htm

It creates subclasses of DefaultMutableNode adding a "isVisible" property rather then actually removing/adding nodes from the TreeModel. Pretty sweet I think, and it solved my filtering problem neatly.