Wichtig ist das du bei größeren TTreeNodes niemals über "Items[i]" iterierst! sonder immer mit GetFirstSibling, GetNexSibling und GetFirstChild im DFS stil den baum durchläufst!
Auch wiederholtes abfragen von "AbsoluteIndex" sollte man in großen Bäumen nicht durchführen, wenn es nicht sien muss, denn das führt auch zu einem ewigen durch den Baum hangeln....wenn der Baum sehr groß ist.
Am besten man schreibst sich einen Iterator für den Baum um Suchen oder Massenhafte Änderungen oder Kopien von oder an Baumknoten durchzuführen.
Ich hatte mal einen TTreeView immer wieder in einen Cache kopiert, über Items[i].... und daraus wieder hergestellt...Daraus gelernt.. auch "Assign" iteriert einfach über die Items[i]
und dann dauert es ewig bis 2500 Nodes kopiert wurden, weil die getItem metode hinter Items[i] immer von neuem wieder anfängt das I-te Item abzuzählen...
Intern werden dann 3126250 Knoten abgelaufen um 2500 Knoten zu iterieren....
Also Kein Assign, kein AbsoluteIndex, Kein Items.count und kein Items[i] benutzen.
Einen DFS-Iterator benutzen!
Oder einfach nur kleine Bäume verwenden...
Sowas in der art
Delphi-Quellcode:
type
TTreeNodeWorkFunction = reference to Function(aTreeNode:TTreeNode): TTreeNode;
Function ForEachItem(Nodes:TTreenodes; aWorkFunction:TTreeNodeWorkFunction; const LevelMaxFilter:Integer = -1 ):TTreenode;
var currentNode, nextNode:TTreeNode;
Begin
Function ForThisNode(aNode:TTreenode; aWorkFunction:TTreeNodeWorkFunction; const LevelMaxFilter:Integer = -1):TTreeNode;
var currentNode, nextNode:TTreeNode;
Begin
Result := nil;
if (LevelMaxFilter = -1) or (Anode.Level < LevelMaxFilter ) then
Begin
currentNode := aNode.getFirstChild;
While assigned(CurrentNode) Do
Begin
nextNode := currentNode.getNextSibling;//NextNode Ermitteln für den fall das CurrentNode gelöscht wird
result := ForThisNode(currentNode,aWorkFunction,LevelMaxFilter);
if assigned(Result) then
nextNode := nil; // Bei Suche direkt abbrechen
CurrentNode := NextNode;//Navigation zum Sibling
End;
end;
if not assigned(Result) then
Result := aWorkFunction(aNode);
End;
Begin
Result := nil;
currentNode := Nodes.GetFirstNode;
While assigned(currentNode) do // für alle wurzeln....
Begin
nextNode := currentNode.getNextSibling;//NextNode Ermitteln für den fall das CurrentNode gelöscht wird
Result := ForThisNode(currentNode,aWorkFunction,LevelMaxFilter);
if assigned(Result) then
nextNode := nil; // Bei Suche direkt abbrechen
CurrentNode := NextNode;//Navigation zum Sibling
End;
end;