2011-11-21 8 views

risposta

23

Espandendo la risposta di @ mKorbel e come discusso in How to Use Trees, è possibile cercare ricorsivamente il proprio TreeModel e ottenere il nodo . Una volta ottenuto lo path desiderato, è facile rivelarlo nell'albero.

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

Addendum: Ecco un modo per "ottenere un 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; 
} 
+0

my (wild :-) credo che "ottenere un TreePath" sia il cuore del problema - non la scienza missilistica, ma non c'è alcun esempio di farlo nel tutorial (o io essere cieco, un non-zero probabilità ) – kleopatra

+0

@kleopatra: buon punto; più sopra. – trashgod

1

Ecco un esempio di come passare da un albero in una ricerca:

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); 
       } 
      } 
     } 
    } 
+0

Buon esempio; considera anche 'text.addActionListener (this)'; vedere anche [* Initial Threads *] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html). – trashgod

2

Sto assumendo vuoi dire che si desidera trovare un nodo con una particolare stringa, giusto? Le altre risposte spiegano i modi per farlo usando l'approccio enumerativo ... (e sono sicuro che sono tutti consapevoli del fatto che nel mondo reale dovresti anche prevedere la possibilità che più di un nodo abbia la stringa cercata, ecc.)

Ma ci sono potenzialmente altri modi, più sexy, di farlo. Ad esempio, se metti tutti i nodi in un tipo collection (ArrayList, ecc.) Come sono stati inseriti nell'albero (e li hai rimossi man mano che sono stati rimossi, inclusa la rimozione esplicita di tutti i loro discendenti) ... e se anche implementato le cose in modo che due nodi fossero considerati "uguali" se avessero lo stesso risultato da toString (o implementato uno Comparator che lo ha fatto), potreste quindi far uscire facilmente il nodo (o i nodi) nello ArrayList corrispondente, e poi andare

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

Uno dei punti di alberi è che in realtà è il percorso al nodo (a volte chiamata "briciole di pane"), che è la vera "identità" di un dato nodo. In termini di mostrate String valori questo significa che si potrebbe avere, nello stesso albero:

percorso: "Peter" - "Piper" - "in salamoia" - "pepe"
percorso: "specialità culinarie" - "spezie "- 'pepe'
percorso: 'I miei preferiti' - 'alimentare' - 'condimenti' - 'pepe'

e così dire che si desidera cercare, quindi selezionare o evidenziare, uno di questi" pepe "nodi ... non è davvero molto efficiente avere un approccio di enumerazione" forza bruta "per ciascuno degli elementi lungo questo percorso (più grande è l'albero, peggio è il problema, ovviamente).

Usando il mio suggerimento diventa abbastanza semplice: basta dividere il vostro percorso "briciole di pane", a partire dalle radici, o dovunque, e poi, come visualizzi in dettaglio l'albero, utilizzare node.isNodeDescendant() sul nodo "superiore" (s) (cioè quelli più lontani dalla radice) hai già trovato (qui, i 3 nodi "pepe"): se volevi il primo percorso sopra, dovresti prima trovare il nodo "Pietro", e subito dopo l'unico nodo "pepe" che potrebbe soddisfare il test isNodeDescendant produrrebbe l'intero percorso che stai cercando.

* Alcune forme di raccolta hashing sarebbero ancora più efficienti, ovviamente. Ma questa è una considerazione solo se hai molte migliaia o più nodi nel tuo albero.

Problemi correlati