12

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?

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
Amanda S
  • 3,266
  • 4
  • 33
  • 45
  • this is an outdated and less informative thread than this duplicate: http://stackoverflow.com/questions/9234297/filtering-on-a-jtree – bobjandal Aug 15 '12 at 09:48

7 Answers7

9

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);
      }
    }
  }
Amanda S
  • 3,266
  • 4
  • 33
  • 45
3

You should be aware of GlazedLists. It's a fantastic library for doing complex table transformations with little effort. They've also expanded to trees too. It may require a little refactoring of your existing code to get it into the GlazedLists way of working. But check out the demo and the webcasts to see how powerful it is. (It's one of the essential Swing libraries in my view, and it's open source.)

andyroberts
  • 3,458
  • 2
  • 37
  • 40
  • I see nothing in GlazedLists for trees: https://java.net/projects/glazedlists/sources/svn/show/trunk/source/ca/odell/glazedlists/swing?rev=2375 Please can you tell us where you found its filtering APIs for trees? – gouessej Apr 07 '14 at 14:28
  • @gouessej it's within the extensions folder: https://java.net/projects/glazedlists/sources/svn/show/trunk/extensions/treetable/source/ca/odell/glazedlists/swing?rev=2375 – andyroberts Apr 07 '14 at 14:48
2

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.

Martin Wickman
  • 19,662
  • 12
  • 82
  • 106
  • I recently needed to implement filtering in a JTree and this solution was by far the cleanest and simplest. – Aaron Nov 28 '16 at 09:01
2

Have you tried JXTree ? (unfortunately the website is down right now, but you can google for mirrors)

Davide
  • 17,098
  • 11
  • 52
  • 68
  • 1
    Actually, the support of filters in JXTree has never been implemented even though it was planned, I just see a protected unused field about filtering in its source code. – gouessej Apr 07 '14 at 18:31
1

If you're looking for a commercial solution, JideSoft has a filterable treemodel. Other than that, SwingX has a Filter API which'll work on JXTable, JXTreeTable, JXTree, and JXList.

Aakash
  • 329
  • 1
  • 4
  • Thanks! I tried the Jide one, but I couldn't get it to do what I wanted. I will look into the SwingX API when I get a chance. – Amanda S May 14 '09 at 18:18
  • What exactly are you trying to do? If you provide details, I might be able to give some specific code. From what I understand, the filtered leaves from the search criteria will be shown, along with their parents. This is shown in their webstart demo, at http://www.jidesoft.com/products/download.htm, 'Demo for all JIDE Products'. In this, look at the QuickFilter (Tree) Demo. – Aakash May 15 '09 at 07:16
  • As I recall, I was having trouble getting the Jide tree model to show the visible children of invisible parents. – Amanda S May 18 '09 at 17:40
  • I'm not able to follow you. Can you give a detailed explanation? – Aakash May 21 '09 at 06:31
  • Amanda S, did you mean that your filter indicates that the parents should be hidden except when at least one of their children is visible? This kind of case is handled by this code: http://www.adrianwalker.org/2012/04/filtered-jtree.html – gouessej Apr 07 '14 at 14:31
  • Actually, the support of filters in JXTree has never been implemented even though it was planned, I just see a protected unused field about filtering in its source code. – gouessej Apr 07 '14 at 18:32
0

So long as it is still a tree you are displaying, then TreeModel that filters you existing TreeModel should be simple enough.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • Can you explain this further? – Amanda S May 06 '09 at 21:24
  • What do you want to know. You'll find it easier to find examples that do the same to TableModel. You want to create a TreeModel that delegates to your current model, but removes the nodes you don't want to appear. I suggest, at least to start with, you make all the event propagate as structureChanged (although come to think of it that'll cause the tree expansion to collapse). – Tom Hawtin - tackline May 06 '09 at 23:52
  • 1
    Part of the problem is that "removing nodes that I don't want to appear" removes their children too, even though I might want to show them. – Amanda S May 07 '09 at 00:23
  • Your going to need some kind of parent there. JTree (more importantly the PL&Fs) don't have a way to represent a child with an elided parent. If you want something which changes the way a tree is drawn, you'll need to get inside *specific* PL&F implementations. – Tom Hawtin - tackline May 07 '09 at 00:42
  • I could add the node to a "visible" ancestor (or the root, if all the node's ancestors are hidden), but this is a pain if I ever unhide any of the nodes in between. – Amanda S May 07 '09 at 01:22
0

Leverage the code you use to build your TreeNode(s) and rebuild the TreeNode(s) only including the elements you want. Set the root node on the TreeModel with the filtered root node.

user101884
  • 717
  • 3
  • 7
  • 1
    It's doable but when you set another model, JTree does a lot of things under the hood, especially if it detects a structural change. It's not very good in terms of performance, both for speed and memory footprint. – gouessej Apr 07 '14 at 18:33