Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to search a particular node in jtree and make that node expanded.?

Tags:

java

swing

jtree

I am having a jtree with 100 nodes. now i want to search particular node from that tree and make that node expanded..? How can i solve this problem.?

like image 378
ManthanB Avatar asked Nov 21 '11 10:11

ManthanB


3 Answers

Here is an example of how to cycle through a tree in a search :

    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    import java.util.Enumeration;
    import java.util.List;

    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextField;
    import javax.swing.JTree;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreePath;

    public class TreeDemo extends JFrame implements ActionListener{
        private static final long serialVersionUID = 1L;
        public JTree tree;
        public JButton button;
        public JTextField text;

        public TreeDemo() {

            button = new JButton("Enter search text below and click");
            text = new JTextField();


            button.addActionListener(this);

            tree = new JTree();
            DefaultMutableTreeNode root = new DefaultMutableTreeNode( "Deck" );
            DefaultMutableTreeNode itemClubs= new DefaultMutableTreeNode( "Clubs" );
            addAllCard( itemClubs );
            root.add( itemClubs );

            DefaultMutableTreeNode itemDiamonds = new DefaultMutableTreeNode( "Diamonds" );
            addAllCard( itemDiamonds );
            root.add( itemDiamonds );

            DefaultMutableTreeNode itemSpades = new DefaultMutableTreeNode( "Spades" );
            addAllCard( itemSpades );
            root.add( itemSpades );

            DefaultMutableTreeNode itemHearts = new DefaultMutableTreeNode( "Hearts" );
            addAllCard( itemHearts );
            root.add( itemHearts );

            DefaultTreeModel treeModel = new DefaultTreeModel( root );
            tree = new JTree( treeModel );

            JScrollPane scrollPane = new JScrollPane(tree);
            getContentPane().add(scrollPane, BorderLayout.CENTER);
            getContentPane().add(button, BorderLayout.NORTH);
            getContentPane().add(text, BorderLayout.SOUTH);

            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(375, 400);      
        }

        public void addAllCard( DefaultMutableTreeNode suit ) {
            suit.add( new DefaultMutableTreeNode( "Ace" ) );
            suit.add( new DefaultMutableTreeNode( "Two" ) );
            suit.add( new DefaultMutableTreeNode( "Three" ) );
            suit.add( new DefaultMutableTreeNode( "Four" ) );
            suit.add( new DefaultMutableTreeNode( "Five" ) );
            suit.add( new DefaultMutableTreeNode( "Six" ) );
            suit.add( new DefaultMutableTreeNode( "Seven" ) );
            suit.add( new DefaultMutableTreeNode( "Eight" ) );
            suit.add( new DefaultMutableTreeNode( "Nine" ) );
            suit.add( new DefaultMutableTreeNode( "Ten" ) );
            suit.add( new DefaultMutableTreeNode( "Jack" ) );
            suit.add( new DefaultMutableTreeNode( "Queen" ) );
            suit.add( new DefaultMutableTreeNode( "King" ) );
        }

        public final DefaultMutableTreeNode findNode(String searchString) {

            List<DefaultMutableTreeNode> searchNodes = getSearchNodes((DefaultMutableTreeNode)tree.getModel().getRoot());
            DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();

            DefaultMutableTreeNode foundNode = null;
            int bookmark = -1;

            if( currentNode != null ) {
                for(int index = 0; index < searchNodes.size(); index++) {
                    if( searchNodes.get(index) == currentNode ) {
                        bookmark = index;
                        break;
                    }
                }
            }

            for(int index = bookmark + 1; index < searchNodes.size(); index++) {    
                if(searchNodes.get(index).toString().toLowerCase().contains(searchString.toLowerCase())) {
                    foundNode = searchNodes.get(index);
                    break;
                }
            }

            if( foundNode == null ) {
                for(int index = 0; index <= bookmark; index++) {    
                    if(searchNodes.get(index).toString().toLowerCase().contains(searchString.toLowerCase())) {
                        foundNode = searchNodes.get(index);
                        break;
                    }
                }
            }
            return foundNode;
        }   

        private final List<DefaultMutableTreeNode> getSearchNodes(DefaultMutableTreeNode root) {
            List<DefaultMutableTreeNode> searchNodes = new ArrayList<DefaultMutableTreeNode>();

            Enumeration<?> e = root.preorderEnumeration();
            while(e.hasMoreElements()) {
                searchNodes.add((DefaultMutableTreeNode)e.nextElement());
            }
            return searchNodes;
        }

        public static void main(String[] args) {
            TreeDemo app = new TreeDemo();
            app.setVisible(true);


        }


        public void actionPerformed(ActionEvent e) {
            String search = text.getText();
                if(search.trim().length() > 0 ) {

                DefaultMutableTreeNode node = findNode(search);                
                if( node != null ) {
                    TreePath path = new TreePath(node.getPath());
                    tree.setSelectionPath(path);
                    tree.scrollPathToVisible(path);
                }  
            }
        }
    }
like image 45
Constantin Avatar answered Oct 12 '22 23:10

Constantin


Expanding on @mKorbel's answer and as discussed in How to Use Trees, you can search your TreeModel recursively and obtain a TreePath to the resulting node. Once you have the desired path, it's easy to reveal it in the tree.

tree.setSelectionPath(path);
tree.scrollPathToVisible(path);

Addendum: Here's one way to "obtain a TreePath."

private TreePath find(DefaultMutableTreeNode root, String s) {
    @SuppressWarnings("unchecked")
    Enumeration<DefaultMutableTreeNode> e = root.depthFirstEnumeration();
    while (e.hasMoreElements()) {
        DefaultMutableTreeNode node = e.nextElement();
        if (node.toString().equalsIgnoreCase(s)) {
            return new TreePath(node.getPath());
        }
    }
    return null;
}
like image 64
trashgod Avatar answered Oct 12 '22 23:10

trashgod


I'm assuming you mean you want to find a node with a particular string, right? The other answers explain ways to do this using the enumeration approach... (and I'm sure they are all aware that in the real world you'd also have to cater for the possibility of more than one node having the sought string, etc.)

But there are potentially other, sexier, ways of doing it. For example, if you put all nodes in a collection of some kind (ArrayList, etc.*) as they were inserted in the tree (and removed them as they were removed, including explicitly removing all their descendants)... and if you also implemented things so that two nodes were deemed "equal" if they had the same result from toString (or implemented a Comparator which did that), you could then easily pop out the actual node (or nodes) in the ArrayList which match, and then go

tree.expandPath( new TreePath( node_found.getPath())

One of the points of trees is that really it is the path to the node (sometimes called the "breadcrumbs") which is the real "identity" of any given node. In terms of displayed String values this means that you might have, in the same tree:

path: "Peter" - "Piper" - "pickled" - "pepper"
path: "Culinary specialities" - "spices" - "pepper"
path: "My favourites" - "food" - "condiments" - "pepper"

And so say you want to search for, and then select or highlight, one of these "pepper" nodes... it is not really very efficient to have a "brute force" enumeration approach for each of the elements along this path (the bigger the tree, the worse the problem of course).

Using my suggestion it becomes pretty easy: just divide up your "breadcrumbs" path, starting at root, or wherever, and then, as you drill down into the tree, use node.isNodeDescendant() on the "higher" node(s) (i.e. those further from the root) you have already found (here, the 3 "pepper" nodes): if you wanted the first path above, you would first find node "Peter", and then immediately afterwards the only "pepper" node which could satisfy the isNodeDescendant test would yield the whole path you're looking for.

* Some form of hashing collection would be even more efficient, of course. But this is a consideration only if you have many thousands, or more, nodes in your tree.

like image 40
mike rodent Avatar answered Oct 12 '22 23:10

mike rodent