2012-10-13 25 views
5

Mam problem z widocznością węzłów JTree używam dla mojego JDialog. Kiedy chcę dodać nowy węzeł do modelu, JTree nie jest odświeżane.JDialog - Odśwież dynamicznie dodane węzły w JTree

Dziwne, że węzły aktualizują się tak, jak powinny, jeśli ustawię setRootVisible (true).

Oto kod. Dzięki z góry

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

Istnieją dwa czynniki łączące ukrywanie dodanych węzłów. 1) Korzeń nie jest widoczny. 2) Węzły nie są rozwijane po zaktualizowaniu modelu. –

Odpowiedz

7

Upewnij się, aby poszerzyć drogę od rodzica nowego węzła do korzenia przy każdym dodać nowy węzeł dziecko:

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

Tak, to działa jak zaklęcie, ale nadal mnie to miesza. Nie muszę tego robić dla JFrame. Dzięki. – bioMind

+1

@ user1503578 Zwykle węzeł główny JTree jest rozszerzany, ale gdy drzewo jest tworzone, węzeł główny nie ma żadnych potomków, więc nie można go rozwinąć. Zauważ, że nawet gdy węzeł główny nie jest widoczny, jego rozwinięty stan nadal kontroluje widoczność jego potomków. Później, gdy dodasz nowe węzły, nie będą one wyświetlane, ponieważ root jest zwinięty. –

+0

@GeoffReedy w gruncie rzeczy prawda, ale drażni mnie, że argumentowałbym _cannot_ - jest to szczegół implementacji modelu :-) – kleopatra

3

Proszę również sprawdzić innym rozwiązaniem:

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

API mówi:

wywołać metodę ponownego ładowania, jeśli zmodyfikowano TreeNodes, od których zależy ten model . Model powiadomi wszystkich swoich odbiorców o zmianie modelu .

Dla szybkiego sprawdzenia spróbuj wykonać następujące czynności:

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

proszę zobaczyć następującą odpowiedź więcej szczegółów:

+0

nie używaj przeładowania na prostych zmianach, zamiast tego upewnij się, że model powiadamia się odpowiednio (defaultTreeModel będzie na insertNodeInto) – kleopatra

3

Odpowiedź przez @JBNizet jest poprawna , podsumowując:

  • wstawienie węzeł ma automatyczne wpływ na stan rozprężania dominującej
  • tak, aby mieć pewność, że nowo dodaje dziecko jest widoczna, to jej rodzic musi być rozszerzona

wtrącić bitu alternatywą api, aby dziecko widoczny:

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

chodzi o komentarz przez @Geoff Reedy (pogrubienie przeze mnie):

Zwykle węzeł główny z JTree jest rozwinięty, ale gdy drzewo jest tworzony, węzeł główny nie miał dzieci, więc nie można rozszerzyć

nie może nie jest tak ścisły: czy lub nie można go rozszerzyć (nawet przy zerowych dzieciach) w rzeczywistości zależy od implementacji modelu isLeaf.Prawdopodobnie nigdy korzeniem jest liść (nawet bez dzieci), ponieważ jego istotą jest nie być :-) można osiągnąć

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

}; 

z takiej implementacji, korzeń jest zawsze rozszerzony (root widoczne lub nie) i nowo wstawione bezpośrednie dzieci pojawią się, nie czyniąc ich wyraźnie widocznymi.