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
Model based filtering
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 questionTreeModel
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)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
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
JTable
handles the filtering with RowFilter
s, 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
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.