2012-10-13 11 views
5

Ich habe ein Problem mit JTree Knoten Sichtbarkeit ich für meine JDialog verwenden. Wenn ich dem Modell einen neuen Knoten hinzufügen möchte, wird Jtree nicht aktualisiert.JDialog - Aktualisieren dynamisch hinzugefügten Knoten in JTree

Seltsam ist, dass die Knoten genau so aktualisiert werden, wie sie sollten, wenn ich setRootVisible (true) setze.

Hier ist der Code. Vielen Dank im Voraus

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

Es gibt zwei Faktoren, die kombiniert werden, um die hinzugefügten Knoten zu verbergen. 1) Die Wurzel ist nicht sichtbar. 2) Die Knoten werden nicht erweitert, nachdem das Modell aktualisiert wurde. –

Antwort

7

Achten Sie darauf, den Weg von der Mutter des neuen Knotens an der Wurzel jedes Mal, wenn ein neues Kind-Knoten hinzufügen zu erweitern:

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

Ja, das funktioniert wie Charme, obwohl es mich immer noch verwirrt. Ich muss das für JFrame nicht tun. Vielen Dank. – bioMind

+1

@ user1503578 Normalerweise wird der Stammknoten eines JTree erweitert, aber beim Erstellen des Baums hat der Stammknoten keine untergeordneten Elemente, sodass er nicht erweitert werden kann. Beachten Sie, dass selbst wenn der Stammknoten nicht sichtbar ist, der erweiterte Status weiterhin die Sichtbarkeit seiner untergeordneten Elemente steuert. Später, wenn Sie die neuen Knoten hinzufügen, werden sie nicht angezeigt, da das Stammverzeichnis minimiert ist. –

+0

@GeoffReedy grundsätzlich wahr, aber pingelig würde argumentieren die _cannot_ - es ist ein Implementierungsdetail des Modells :-) – kleopatra

3

Bitte überprüfen Sie auch eine andere Lösung:

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

API sagt:

rufen Sie die Reload-Methode auf, wenn Sie die TreeNodes geändert haben, von denen das Modell abhängt. Das Modell benachrichtigt alle seine Listener darüber, dass sich das Modell geändert hat.

Für eine schnelle Überprüfung versuchen Sie Folgendes:

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()); 
    } 
} 

Bitte beachten Sie die folgende Antwort für weitere Informationen:

+0

Verwenden Sie nicht auf einfache Änderungen neu laden, stellen Sie stattdessen sicher, dass das Modell benachrichtigt als geeignet (defaultTreeModel wird auf insertNodeInto) – kleopatra

3

Die Antwort von @JBNizet richtig ist , um zusammenzufassen:

  • einen Knoten auf dem Expansionszustand des Mutter
  • so sicher zu machen, hat keinen Automatismus Einsetzen, dass das neu eingefügte Kind sichtbar ist, muss die Mutter

erweitert werden, um zu werfen in einem wenig

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

In Bezug auf einen Kommentar von @Geoff Reedy (bolding von mir):

Alternative api das Kind sichtbar zu machen

Normalerweise wird der Wurzelknoten eines JTree erweitert, aber wenn der Baum erstellt wird, ist der Wurzelknoten hat keine Kinder, so dass es nicht erweitert werden kann

die nicht nicht so streng ist: ob oder nicht kann es erweitert werden (auch mit Null Kinder) hängt tatsächlich von der Implementierung des Modells IsLeaf.Argumentieren, ist die Wurzel nie ein Blatt (auch ohne Kinder), weil sein Wesen ist nicht zu sein :-) mit

erreicht werden kann
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(); 
    } 

}; 

mit einer solchen Implementierung ist die Wurzel immer erweitert (root sichtbar oder nicht) und neu eingefügte direkte Kinder werden auftauchen, ohne sie explizit sichtbar zu machen.