Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - TreeView durchsuchen
Max Payne - Sa 16.07.05 13:06
Titel: TreeView durchsuchen
Auch wenn ich die Frage hier
http://www.delphi-forum.de/topic_Treeview+zur+Laufzeit+quotbefuellenquot_45298.html schon gestellt habe eröfne ich ein neues Topic da es ja eigentlich nichts mehr mit dem alten zu tun hat (irgendwo hab ich gelesen: Neue Frage, neues Topic).
Ich möchte die verschiedenen Ebenen bei einem Treeview getrennt durchsuchen. Ich kann mit
for i := 0 to (TreeView1.Items.Count - 1) do die gesamte Liste durch gehen aber da ich über 2k Einträge habe dauert das ziemlich lange und enthält Fehler. Also ist es möglich einzelne Ebenen zu durchsuchen? Wenn ja wie?
P.S.: Noch ein Topic zu TreeView :P
Gausi - Sa 16.07.05 13:12
Soviel ich weiss, bekommt man mit GetNextSibling den nächsten Knoten auf derselben Ebene. Kindknoten des aktuellen Knotens werden dadurch übersprungen.
btw: Mit dem VirtualTreeView dürften Geschwindigkeitsprobleme nicht mehr auftreten. Bin gerade dabei, mich da einzuarbeiten, und da kann man 40.000 Knoten in Nullkommanix untersuchen...
Max Payne - Sa 16.07.05 13:16
danke ich werds probieren. Naja das mit der Geschwindigkeit... Bisher hab ich versucht das andres hinzubekommen jedoch brauchee ich dazu in der schleife nochmal 3 Schleifen die nochmal durchsuchen... Nicht sehr gut gelöst aber ich war ja nur am probieren :wink:
Klabautermann - Sa 16.07.05 15:36
Hallo,
zuersteinmal, du kannst über die Eigenschaft
Level abfragen auf welcher Ebene sich der aktuell berachtete Knoten befindet. tTreeItems bietet dir mit GetFirstNode eine Möglichkeit den ersten Knoten des Baumes zu suchen. Bei tTreeItem kannst du mit GetFirstChild und GetNextChild sowie mit GetNext und natürlich den genannten GetNextSibling navigieren. Mit einer Kombiation dieser Funktionen kannst du sicherlich viel Geziehlter suchen als mit deinen Schleifen. Zum einen kannst du deine suche Reursiv gestalten, was sich bei Bäumen immer anbietet, auch kannst du, wenn du in einer Sackgasse belandet bist kannst du die suche an der Stelle einfacher abbrechen.
Folgende Funktion ist nicht getestet (da ich keine lust habe mit einen Beispielbaum auf zu bauen) aber ich hoffe sie Funktiniert und ist schneller als deine variante, sehe es ansonsten als Konzeptstudie ;):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| function FindNodeOnLevel(aParentNode: tTreeNode; aCaption: String; aLevel: Integer): tTreeNode; var ActNode : tTreeNode; begin Result := nil; if (aParentNode <> nil) and (aParentNode.HasChildren) and (aParentNode.Level < aLevel) then begin ActNode := aParentNode.getFirstChild; while (ActNode <> nil) and (Result = nil) do begin if (ActNode.Level < aLevel) and (ActNode.HasChildren) then Result := FindNodeOnLevel(ActNode, aCaption, aLevel) else if (ActNode.Level = aLevel) and (AnsilowerCase(ActNode.Text) = AnsiLowerCase(aCaption)) then Result := ActNode; ActNode := aParentNode.GetNextChild(ActNode); end; end; end; |
Wie du (wenn du dich ein wenig reingedacht erkennst) sucht diese Rekursiv nach einen Knoten mit einer bestimmten Bezeichnung (G&K Schreibung egal) auf einer Bestimmten ebene (Hauptknoten haben Level 0). Hierbei werden Knoten die auf einem Level welches größer ins als das gesuchte nciht beachtet und sobalt der Knoten gefunden wurde wird auch nicht mehr weiter gesucht. Wird der Knoten nicht gefunden (nicht existent) liefert die Funktion
NIL zurück.
Ein Aufruf könnte so aussehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| procedure TForm1.Button1Click(Sender: TObject); var SearchNode : tTreeNode; begin SearchNode := FindNodeOnLevel(TreeView1.Items.GetFirstNode, 'Gesucher Text', 4); end; |
Noch ein kleiner hinweis zur Geschwindigkeit. Wenn du etwas an den Items änders (z.B. auch beim Baum aufbauen) kannst du das erheblich beschleunigen, wenn du vorher
TreeView1.Items.BeginUpdate; aufrufen und hinterher
TreeView1.Items.EndUpdate; aufrufen, das verhindert, dass nach jeder änderung der Baum neu gezeichnet wird. Aus sicherheitsgründen sollte das in einer Try Finally konstruktion geschehen, damit der Baum bei einem Fehler nicht tot bleibt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| TreeView1.Items.BeginUpdate; try finally TreeView1.Items.EndUpdate; end; |
So, ich hoffe das bringt dich weiter.
Klabautermann
Max Payne - Sa 16.07.05 17:17
Auch wenn ich noch nicht ganz dahinter gestiegen bin (mein Kopf dröhnt durch den Mist den ich selbst verzapft hab) sieht es nicht schlecht aus. probieren werd ich das heute nicht mehr denke ich.
Bei meinem aktuellem versuch klappt es (fast :( ). Falls Interesse besteht kann ich Posten was ich mir Gedacht hab.
Naja wie gesagt erstmal den Kopf frei bekommen und weiter...
Max Payne - Di 19.07.05 09:36
Ok klappt soweit alles. Danke.
Allerdings musste ich die Funktion etwas anpassen um auch in der ersten ebene suchen zu können ;)
Am ende schauts so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| MyNode1 := ProvinzenTree.Items.AddChild(nil, Provinzen[1].Kontinent); for i := 1 to 2600 do begin MyNode1 := FindNodeOnLevel(nil, Provinzen[i].Kontinent, 0); if MyNode1 = nil then MyNode1 := ProvinzenTree.Items.AddChild(nil, Provinzen[i].Kontinent); MyNode2 := FindNodeOnLevel(MyNode1, Provinzen[i].Region, 1); if MyNode2 = nil then MyNode2 := ProvinzenTree.Items.AddChild(MyNode1, Provinzen[i].Region); MyNode3 := FindNodeOnLevel(MyNode2, Provinzen[i].Gebiet, 2); if MyNode3 = nil then MyNode3 := ProvinzenTree.Items.AddChild(MyNode2, Provinzen[i].Gebiet); MyNode4 := FindNodeOnLevel(MyNode3, Provinzen[i].Name, 3); if MyNode4 = nil then MyNode4 := ProvinzenTree.Items.AddChild(MyNode3, Provinzen[i].Name); end; |
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!