Einzelnen Beitrag anzeigen

choose

Registriert seit: 2. Nov 2003
Ort: Bei Kiel, SH
729 Beiträge
 
Delphi 2006 Architect
 
#5

Re: tree items zählen die rot markiert sind

  Alt 16. Jan 2004, 12:17
Hallo Micha,

mit dem von gothic_mike vorgeschlagenen Ansatz, zählst Du faktisch die "Anzahl vorgenommenen Rotfärbungen beim Zeichnen". Dieser Ansatz ist in sofern kritisch, als dass Du nicht sicherstellen kannst, dass wirklich jeder Knoten gezeichnet wird (außerhalb des ClientRects des Trees, Invisible, minimierter Zweig, etc) und Du keine unmittelbare Einflussmöglichkeit auf das Eintreten des Zeitpunkts des zeichnen kannst, so dass auch ein Einsatz der Form
Delphi-Quellcode:
Self.FGefunden:= 0;
Self.EdtSuchen.Text:= SomeValue;
ShowMessage(IntToStr(Self.FGefunden));
keine brauchbare Lösung bietet.

Du wirst nicht um ein Traversieren (alle Knoten einer Struktur durchlaufen) herum kommen und jeden Knoten erneut gegen das Kriterium prüfen müssen. Leider kenne ich zu diesem Zweck keine vorgefertigte Methode, die mit einer CallBack-Funktion aufgerufen werden kann und das Missbrauchen von CustomSort halte ich ebenfalls für kritisch.

Aus diesem Grund biete ich Dir an dieser Stelle eine entsprechene Traversierungsmethode für Deinen Spezialfall an. Zunächst führe ich hierzu die private Methode DoesNodeMatchCriteria ein, die genau dann True zurückgibt, wenn ein Knoten das von Dir beschriebene Kriterium erfüllt:
Delphi-Quellcode:
function TForm1.DoesNodeMachCriteria(const ANode: TTreeNode): Boolean;
begin
  Result:= AnsiStartsText(Self.EdtSuchen.Text, ANode.Text);
end;
so dass zunächst Deine Zeichenroutine vereinfacht werden kann:
Delphi-Quellcode:
procedure TForm1.treeCustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  if DoesNodeMatchCriteria(Node) then
    Sender.Canvas.Font.Color:= clRed;
end;
anschließend führe ich die tatsächliche Zählmethode CountMatchingNodes ein:
Delphi-Quellcode:
function TForm1.CountMatchingNodes: Cardinal;
  procedure TraverseNodes(const ANode: TTreeNode; var ASum: Cardinal);
  var
    myNode: TTreeNode;
  begin
    myNode:= ANode;
    // iterate every node at this level
    while Assigned(myNode) do
    begin
      if DoesNodeMatchCriteria(myNode) then
        Inc(ASum);

      // traverse recursive
      TraverseNode(myNode.getFirstChild, ASum);

      myNode:= myNode.getNextSibling;
    end;
  end;

begin
  Result:= 0;
  TraverseNodes(TreeView1.Items.GetFirstNode, Result);
end;
Sie basiert im Wesentlichen auf der Unterprozedur TraverseNodes, die für alle Knoten auf derselben Ebene wie dem übergebenen Knoten überprüft, ob sie dem Kriterium entsprechen und einen als Referenz übergebenen Zähler um diese Anzahl erhöht
Delphi-Quellcode:
myNode:= ANode;
while Assigned(myNode) do
begin
  if DoesNodeMatchCriteria(myNode) then
    Inc(ASum);
  myNode:= myNode.getNextSibling;
end;
weil die Unteroutine mit dem Wurzelelement des Treeviews aufgerufen wird und der als Referenz übergebene Wert dem Wert Result von CountMatchingNodes entspricht, zählt dieser Teil der Lösung bereits alle "roten Knoten" auf der ersten Ebene.

Um nun auch alle Unterknoten der Knoten sowie deren Unterknoten usw zu überprüfen, wende ich eine Rekursion an. Die Unterprozedur TraverseNodes ruft "sich selbst" mit dem ersten Unterknoten der gerade betrachteten Knotens auf, so dass alle Unterknoten auf dieser Ebene überprüft werden. Weil die Routine für jeden Aufruf auf dieselbe Weise verfährt, werden letztlich alle Knoten durchlaufen und überprüft.


Um die Methode CountMatchingNodes nun zu verwenden, kannst Du zB folgendes Schreiben
Delphi-Quellcode:
Self.EdtSuchen.Text:= SomeValue;
ShowMessage(IntToStr(CountMatchingNodes));
gruß, choose
  Mit Zitat antworten Zitat