2009-12-15 11 views
7

Mam JTree z około 100000 węzłów lub więcej. Teraz chcę rozwinąć całe drzewo. Aby to zrobić, korzystam z rozwiązania, które znalazłem here.Przyspieszenie rozwiń/zwiń wszystkie węzły JTree

Moim problemem jest to, że rozwijanie tak dużego drzewa trwa około 60 sekund lub dłużej, co nie jest zbyt wygodne. Czy ktoś ma jakieś sugestie, w jaki sposób mogę przyspieszyć ekspansję?

+1

Dlaczego chcesz w pełni rozwinąć JTree o 100 000 węzłów? Tylko ułamek węzłów będzie pasował na ekranie, więc jaka jest korzyść z tego? – Adamski

+0

Przypadek użycia pokazuje użycie części we wszystkich materiałach w naszym datastructur.To może teoretycznie prowadzić do tak dużej ilości danych. W tej chwili próbuję dowiedzieć się, co jest możliwe z JTree technicznie (szczególnie w porównaniu do elementu VirtualTreeView Delphi/C++) – hagt

Odpowiedz

1

Myślę, że trzeba wymyślić strategię wyświetlania, albo szerokość pierwsza (spójrz na wszystkie bezpośrednie dzieci), albo głębia pierwsza (spójrz na wszystkich potomków tylko jednego dziecka). 100 000 to o wiele za dużo węzłów do wyświetlenia na ekranie, a będziesz musiał pomyśleć o panoramowaniu i powiększaniu. Powinieneś pomyśleć o filtrach, które mogłyby wybrać podzbiory potomków, które chcesz.

Jedną z strategii może być wyświetlanie najlepszych dzieci, a gdy mysz wejdzie do dziecka, wyświetlenie wszystkich jego potomków i kiedy opuścisz je zwinąć. W ten sposób możesz nawigować po drzewie wyświetlającym bieżące poddrzewo.

0

Tak, ponownie przemyśl swój element interfejsu użytkownika. JTree nie jest tym, czego szukasz, aby pokazać 100 000 węzłów. Użyj czegoś tam, gdzie możesz zobaczyć tabelę i kliknij elementy, aby przejść do elementu tabeli. Następnie przejdź do historii takiej jak bułka z masłem, aby użytkownik mógł nawigować w górę hierarchii ..

Jeśli nalegasz na posiadanie JTree, istnieje sposób, aby przejąć sposób, w jaki on odświeża, ale nie wiem, czy to będzie pomóc w rozwiązaniu problemu.

+1

W zasadzie całkowicie się zgadzam, ale teraz próbuję tylko dowiedzieć się, co jest możliwe z JTree. Do tej pory przekonałem się, że drzewo działa dobrze z tak dużymi strukturami danych, jeśli chodzi o przewijanie i przesuwanie. Ale rozbudowywanie wielu węzłów jest niezwykle czasochłonne – hagt

1

Próbowałem rozwiązania, ty też używasz.

Po mojej opinii przedstawiony tam kod nie jest optymalny: - wywołuje tree.expandPath dla wszystkich węzłów, zamiast wywoływać go tylko dla najgłębszych węzłów niebędących liśćmi (wywoływanie expandPath na węzłach liści nie ma żadnego efektu, zobacz JDK)

Oto poprawiona wersja, która powinna być szybsza:

// If expand is true, expands all nodes in the tree. 
    // Otherwise, collapses all nodes in the tree. 
    public void expandAll(JTree tree, boolean expand) { 
     TreeNode root = (TreeNode)tree.getModel().getRoot(); 
     if (root!=null) { 
      // Traverse tree from root 
      expandAll(tree, new TreePath(root), expand); 
     } 
    } 

    /** 
    * @return Whether an expandPath was called for the last node in the parent path 
    */ 
    private boolean expandAll(JTree tree, TreePath parent, boolean expand) { 
     // Traverse children 
     TreeNode node = (TreeNode)parent.getLastPathComponent(); 
     if (node.getChildCount() > 0) { 
      boolean childExpandCalled = false; 
      for (Enumeration e=node.children(); e.hasMoreElements();) { 
       TreeNode n = (TreeNode)e.nextElement(); 
       TreePath path = parent.pathByAddingChild(n); 
       childExpandCalled = expandAll(tree, path, expand) || childExpandCalled; // the OR order is important here, don't let childExpand first. func calls will be optimized out ! 
      } 

      if (!childExpandCalled) { // only if one of the children hasn't called already expand 
       // Expansion or collapse must be done bottom-up, BUT only for non-leaf nodes 
       if (expand) { 
        tree.expandPath(parent); 
       } else { 
        tree.collapsePath(parent); 
       } 
      } 
      return true; 
     } else { 
      return false; 
     } 
    } 
2

miałem ten sam problem z drzewem zawierającej 150 000 węzłów (z ponad 19 000 otwieranymi węzłów). I dzieli się przez 5 Czas trwania rozwiń wszystkie tylko poprzez nadpisanie metody getExpandedDescendants:

JTree tree = new javax.swing.JTree() 
{ 
    @Override 
    public Enumeration<TreePath> getExpandedDescendants(TreePath parent) 
    { 
     if (!isExpanded(parent)) 
     { 
      return null; 
     } 
     return java.util.Collections.enumeration(getOpenedChild(parent, new javolution.util.FastList<TreePath>())); 
    } 

    /** 
    * Search oppened childs recursively 
    */ 
    private List<TreePath> getOpenedChild(TreePath paramTreeNode, List<TreePath> list) 
    { 
     final Object parent = paramTreeNode.getLastPathComponent(); 
     final javax.swing.tree.TreeModel model = getModel(); 
     int nbChild = model.getChildCount(parent); 
     for (int i = 0; i < nbChild; i++) 
     { 
      Object child = model.getChild(parent, i); 
      final TreePath childPath = paramTreeNode.pathByAddingChild(child); 
      if (!model.isLeaf(child) && isExpanded(childPath)) 
      { 
       //Add child if oppened 
       list.add(childPath); 
       getOpenedChild(childPath, list); 
      } 
     } 
     return list; 
    } 
}; 

Rozwiń wszystkie działania podjąć teraz 5 sekund zamiast 25, a ja wciąż pracuję na poprawę wydajności.

3

Szybki sposób:

JTree jTree; 
for (int i = 0; i < jTree.getRowCount(); i++) { 
     jTree.expandRow(i); 
} 
0

Miałem pewne sukcesy z następującym wzorem:

tree = new JTree(...) 
tree.setLargeModel(true); 

To już przyniósł duże rozszerzenia (150,000) węzły drzewa w dół od 12s -> 3,5 s

Następnie rozszerzyć luzem szybciej:

TreeUI treeUI = tree.getUI(); 
tree.setUI(null); 
try { 
    // perform bulk expansion logic, like in other answers 
} finally { 
    tree.setUI(treeUI); 
} 

Sprowadziło to to do około 1,0 s.

Powiązane problemy