2012-10-13 24 views
5

Tôi gặp vấn đề với khả năng hiển thị nút JTree mà tôi sử dụng cho JDialog của mình. Khi tôi muốn thêm nút mới vào mô hình, Jtree không được làm mới.JDialog - Làm mới các nút được thêm tự động trong JTree

Lạ là các nút đang cập nhật đúng như chúng nên nếu tôi đặt setRootVisible (true).

Đây là mã. Cảm ơn trước

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JTree; 
import javax.swing.tree.DefaultMutableTreeNode; 
import javax.swing.tree.DefaultTreeModel; 

public class TestClass { 

JTree tree; 
DefaultTreeModel dm; 
JDialog dialog; 

public TestClass(){ 
    JFrame frame = new JFrame("title"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 

    JPanel showPane = new JPanel(); 
    showPane.setLayout(new BorderLayout()); 

    dm = new DefaultTreeModel(new DefaultMutableTreeNode("root")); 
    tree = new JTree(dm); 
    tree.setRootVisible(false); 

    JButton button = new JButton("add node"); 
    button.addActionListener(new ActionListener(){ 

     public void actionPerformed(ActionEvent arg0) { 
      DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();   
      dm.insertNodeInto(new DefaultMutableTreeNode("Node " + (root.getChildCount() + 1)), root, root.getChildCount()); 

      int c = root.getChildCount(); 
      System.out.println("child count: " + c); 

      for(int i=0; i<c; i++){ 
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) root.getChildAt(i); 
       System.out.println("has node:" + node.getUserObject().toString()); 
      } 
     } 

    }); 

    showPane.add(tree, BorderLayout.CENTER); 
    showPane.add(button, BorderLayout.PAGE_END); 

    JComponent[] inputComponents = new JComponent[] {showPane}; 

    Object[] opButtons = {"OK"}; 

    JOptionPane optPane = new JOptionPane(inputComponents  
      , JOptionPane.PLAIN_MESSAGE    
      , JOptionPane.CLOSED_OPTION    
      , null          
      , opButtons        
      , opButtons[0]);        

    optPane.setPreferredSize(new Dimension(400 ,250)); 

    dialog = optPane.createDialog(null, "Create new Application Node"); 
    dialog.setLocationRelativeTo(frame); 
    dialog.setVisible(true); 

    if(optPane.getValue() != null){ 
     System.exit(0); 
    } 

} 

public static void main(String arg[]){ 
    TestClass myClass = new TestClass(); 
} 

}

+1

Có hai yếu tố kết hợp để ẩn các nút được thêm. 1) Gốc không được hiển thị. 2) Các nút không được mở rộng sau khi mô hình được cập nhật. –

Trả lời

7

Hãy chắc chắn để mở rộng con đường từ phụ huynh của nút mới vào thư mục gốc mỗi khi bạn thêm một nút con mới:

DefaultMutableTreeNode newChild = new DefaultMutableTreeNode("Node " + (root.getChildCount() + 1)); 
dm.insertNodeInto(newChild, root, root.getChildCount()); 
tree.expandPath(new TreePath(dm.getPathToRoot(newChild.getParent()))); 
+0

Đúng, nó hoạt động như sự quyến rũ mặc dù nó vẫn làm tôi bối rối. Tôi không phải làm điều này cho JFrame. Cảm ơn. – bioMind

+1

@ user1503578 Thông thường nút gốc của một JTree được mở rộng, nhưng khi cây được tạo, nút gốc không có bất kỳ con nào để nó không thể được mở rộng. Lưu ý rằng ngay cả khi nút gốc không hiển thị, trạng thái mở rộng của nó vẫn kiểm soát khả năng hiển thị của các nút con của nó. Sau đó khi bạn thêm các nút mới, chúng sẽ không được hiển thị vì gốc bị thu gọn. –

+0

@GeoffReedy về cơ bản là đúng, nhưng nitpicking tôi sẽ tranh luận _cannot_ - đó là chi tiết thực hiện của mô hình :-) – kleopatra

3

Hãy cũng kiểm tra giải pháp khác:

DefaultTreeModel model = (DefaultTreeModel) (tree.getModel()); 
    model.reload(); 

API nói:

hãy gọi phương thức tải lại nếu bạn đã sửa đổi TreeNode theo đó mô hình này phụ thuộc. Mô hình sẽ thông báo cho tất cả người nghe rằng mô hình đã thay đổi.

Đối với một kiểm tra nhanh hãy thử như sau:

public void actionPerformed(ActionEvent arg0) { 
    DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot(); 
    dm.insertNodeInto(new DefaultMutableTreeNode("Node " + (root.getChildCount() + 1)), root, root.getChildCount()); 

    int c = root.getChildCount(); 
    System.out.println("child count: " + c); 

    DefaultTreeModel model = (DefaultTreeModel) (tree.getModel()); // !!! 
    model.reload(); // !!! 

    for (int i = 0; i < c; i++) { 
     DefaultMutableTreeNode node = (DefaultMutableTreeNode) root.getChildAt(i); 
     System.out.println("has node:" + node.getUserObject().toString()); 
    } 
} 

hãy xem câu trả lời sau để biết thêm chi tiết:

+0

không sử dụng tải lại trên các thay đổi đơn giản, thay vào đó đảm bảo mô hình phù hợp (defaultTreeModel sẽ chèn insertNodeInto) – kleopatra

3

Câu trả lời bởi @JBNizet là đúng , để tóm tắt:

  • chèn một nút không có tác dụng tự động trên trạng thái mở rộng của phụ huynh
  • như vậy để đảm bảo rằng đứa trẻ mới được chèn vào có thể nhìn thấy, cha mẹ của nó phải được mở rộng

Để ném vào một chút api thay thế để làm cho đứa trẻ nhìn thấy được:

dm.makeVisible(new TreePath(newChild.getPath()); 

về một lời nhận xét của @Geoff Reedy (bolding của tôi):

Thông thường các nút gốc của một JTree được mở rộng, nhưng khi cây được tạo ra, các nút gốc không có bất kỳ trẻ em nên nó không thể mở rộng

các không thể không phải là quá nghiêm ngặt: cho dù hay không nó có thể được mở rộng (ngay cả với con số không) phụ thuộc vào thực tế của isLeaf của mô hình.Có thể cho rằng, gốc không bao giờ là một lá (thậm chí không có con), vì bản chất của nó là không thể :-) Có thể đạt được với

final DefaultTreeModel model = new DefaultTreeModel(root) { 

    @Override 
    public boolean isLeaf(Object node) { 
     if (isRoot(node)) { 
      return false; 
     } 
     return super.isLeaf(node); 
    } 

    private boolean isRoot(Object node) { 
     return node != null && node == getRoot(); 
    } 

}; 

với một thực hiện như vậy, gốc rễ luôn mở rộng (root có thể nhìn thấy hay không) và trẻ em trực tiếp mới được chèn sẽ hiển thị mà không hiển thị chúng rõ ràng.