Home » Tutorials » Third-Party-Komponenten » VirtualTreeView

VirtualTreeView

Den Nodes Objekte hinzufügen

Um einem Node ein Objekt hinzuzufügen müssen wir ähnlich vorgehen, als ob wir einem Node Daten übergeben. Eine Variable vom Typ TObject im Record zeigt dann einfach auf unser Objekt. So einfach ist das. 🙂

Objekt erstellen

Zuerst müssen wir dieses Objekt erstellen und deklarieren. Als Objekt benutzen wir einfach eine Klasse.

type
  TTreeDataClass = class
    private
      FTestStr1: String;
      FTestint: Integer;
    published
      property TestStr1: String read FTestStr1 write FTestStr1;
      property TestInt: Integer read FTestInt write FTestInt;
end;

Als Properties kann man hier beliebig viele beliebige Typen verwenden. Es ist genauso wie bei der Komponentenerstellung. Da es sich dabei um eine normale Klassen handelt, stehen Dir alle klassenspezifischen Möglichkeiten zur Verfügung. Du kannst nicht nur Properties deklarieren, sondern auch Funktionen und Proceduren in die Klasse intergrieren. Diese Klasse hat zwei Eigenschaften: Eine String-Eigenschaft „TestStr1“ und eine Integer-Eigenschaft „TestInt“

Über diesem Typ deklaieren wir folgenden Record:

type
  PTreeData = ^TTreeData;
  TTreeData = record
    FObject : TObject;
end;

Zusätzlich zeigt der Pointer PTreeData jetzt auf den Record. Wieso wir jetzt an dieser Stelle einen Record benutzen, wird im nächsten Kapitel klarer. Du ahnst wahrscheinlich schon, dass der Variable „FObject“ des Records später unser oben erstelltes Objekt übergeben wird.

Das Objekt hinzufügen

Die nächsten Zeilen dienen hauptsächlich der Verständnis und tauchen in dieser Form nicht unbedingt im Quelltext auf.

Es wird wie gewohnt ein Node hinzugefügt. Die Adresse des Nodes wird in einer lokalen Variable festgehalten. Dies sollte aus dem 3. Kapitel schon alles bekannt sein.

var
  Node: PVirtualNode;
begin
  Node := VST.AddChild(nil);
  Data := VST.GetNodeData(Node);
end;

Data muss in diesem Falle vom Typ PTreeData sein. PTreeData zeigt wiederum auf die Klasse TTreeData (also Data: PTreeData;). Nun weisen wir der Variable FObject ein neues Objekt zu:

Data^.FObject:=TreeDataClass;

TreeDataClass ist hier eine Instanz der Klasse TTreeDataClass (also TreeDataClass: TTreeDataClass). Im Prinzip wurde das Objekt jetzt zugewiesen.

Die komplette Procedure zum Hinzufügen eines Nodes mit Objekt sieht also in etwa so aus. Das eigentliche Hinzufügen des Nodes habe ich in eine Funktion gesteckt:

function AddVSTObject(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
  AObject: TObject): PVirtualNode;
var
  Data: PTreeData;
begin
  Result:=AVST.AddChild(ANode);
  AVST.ValidateNode(Result,False);
  Data:=AVST.GetNodeData(Result);
  Data^.FObject:=AObject;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  TreeObject: TTreeDataClass;
begin
  VST.NodeDataSize:=SizeOf(TTreeData);
  for I:=1 to 100 do
  begin
    TreeObject:=TTreeDataClass.Create;
    try
      TreeObject.TestStr1:='Node-Nummer: '+IntToStr(I);;
      TreeObject.TestInt:=Random(1000);
      AddVSTObject(VST,nil,TreeObject);
    except
      TreeObject.Free;
    end;
  end;
end;

In diesem Beispiel werden dem Baum 100 Nodes+Objekte hinzugefügt. Das Objekt muss jedes Mal createt werden. Du wunderst dich vielleicht, warum das Objekt in einem except-Block wieder freigegeben wird. Dies hat einen einfachen Grund. Das Objekt soll ja die ganze Zeit erhalten bleiben und nicht schon nach dieser Procedure wieder entfernt werden. Um die Freigabe müssen wir uns später kümmern. Das Objekt soll nur manuell freigegeben werden, wenn es beim Hinzufügen einen Fehler gab (z.B. kein Speicher mehr verfügbar).

Die Funktion AddVSTObject erwartet 3 Parameter. Einmal den Tree, welcher um ein Node bereichert werden soll. Dann als zweiten Parameter den übergeordneten Knoten (soll ein Root-Knoten hinzugefügt werden, muss dieser Parameter auf nil stehen) und als dritten Parameter das Objekt. Als Result gibt die Funktion – genauso wie AddChild – einen Zeiger auf den hinzugefügten Node zurück.

Objekte auslesen

Schön. Jetzt haben wir Objekte hinzugefügt, aber wir wissen noch nicht, wie man die Informationen wieder auslesen kann. Es folgt ein Beispiel.

procedure TForm1.VSTClick(Sender: TObject);
var
  Node: PVirtualNode;
  Data: PTreeData;
begin
  Node:=VST.FocusedNode;
  if not Assigned(Node) then
    Exit;
  Data := VST.GetNodeData(Node);
  Showmessage(TTreeDataClass(Data.FObject).TestStr1);
end;

Einen Teil dieser Procedure wirst du von dem letzten Kapitel her wiedererkennen. Es wird der selektierte Node im OnClick-Ereignis des Trees ermittelt.

Neu sind die letzten beiden Zeilen. Die Variable Data ist wieder ein Zeiger auf die Klasse TTreeData in Form von PTreeData. Mit der Funktion GetNodeData wird dieser Variable die Position des Objekts von dem ausgewählten Node übergeben. Per Typecasting wird dann auf die entsprechende Klasse zugegriffen und der Inhalt der Eigenschaft TestStr wird in einer Showmessage ausgegeben.

Ein Objekt hinzuzufügen unterscheidet sich also kaum, als ob man normale Daten hinzufügen würde.

Freigabe

Wie auch vorhin die Daten, müssen wir auch das Objekt freigeben und evtl. dessen Zeiger auf nil setzen. Der Baum hält an dieser Stelle das Ereignis OnFreeNode bereit, welches ausgelöst wird, wenn der Node freigegeben wird. Wird der Node freigegeben, heißt das aber nicht automatisch, dass auch dessen Daten freigegeben werden. Dafür ist der Programmierer zuständig.

procedure TForm1.vstFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
  Data: PTreeData;
begin
  Data := VST.GetNodeData(Node);
  if not Assigned(Data) then
    exit;
  Data.FObject.Free;
end;

Ein Beispiel zu diesem Kapitel kannst Du hier runterladen.