2011-11-21 72 views

回答

23

在@ mKorbel的回答中進行擴展,並在How to Use Trees中討論,您可以遞歸搜索您的TreeModel並獲得TreePath到結果節點。一旦你有所需的path,很容易在樹中顯示它。

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

附錄:這是「獲得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

我的(狂:-)猜是「獲得TreePath」是問題的核心 - 而不是火箭科學,但在教程中沒有這樣做的例子(或者我是盲人,非零概率) – kleopatra

+0

@kleopatra:好點;更上面。 – trashgod

1

這是通過搜索的樹如何循環的例子:

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

很好的例子;也考慮'text.addActionListener(this)';另請參閱[*初始線程*](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html)。 – trashgod

2

我假設你的意思是你要找到一個特定的字符串中的節點,對不對?其他答案解釋了使用枚舉方法來做到這一點的方法......(我相信他們都知道,在現實世界中,您還必須迎合具有所尋找字符串的多個節點的可能性,等等)

但也有其他更性感的方式來做到這一點。例如,如果您將所有節點放入樹中的某個collectionArrayList等*),並將它們插入樹中(並在刪除它們時刪除它們,包括明確刪除其所有後代)......如果您還實現了一些東西,如果兩個節點的結果與toString的結果相同(或者執行Comparator這樣做),則兩個節點被視爲「相等」,那麼您可以輕鬆地彈出與ArrayList匹配的實際節點(或節點),並且然後去

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

一個樹木的點是,它實際上是路徑來(有時稱爲「麪包屑」)的節點是任何給定節點的真實「身份」。在顯示String值而言,這意味着你可能有,在相同的樹:

道:「彼得」 - 「派」 - 「醃」 - 「辣椒」
道:「特色美食」 - 「香料「 - ‘辣椒’
道:‘我的最愛’ - ‘食物’ - ‘調味品’ - ‘辣椒’

所以說你要搜索的內容,然後選擇或亮點,其中之一」辣椒「節點......沿着這條路徑的每個元素都有一個」暴力「枚舉方法(樹越大,當然問題就越嚴重),效率並不是很高。

使用我的建議,它變得非常簡單:只需將root路徑或任何地方的「麪包屑」路徑分開,然後在深入樹中使用「更高」節點上的node.isNodeDescendant(), (也就是那些距離根的更遠的地方)(這裏是3個「胡椒」節點):如果你想要上面的第一條路徑,你首先要找到節點「Peter」,然後緊接着就是唯一的「胡椒」節點這可以滿足isNodeDescendant測試將產生你正在尋找的整個路徑。

*當然,某種形式的哈希集合會更有效率。但是,只有在樹中有數千個或更多的節點時,纔會考慮這一點。