Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - TTreenode Objekte anhängen


TimKellner - Mi 25.10.06 17:15
Titel: TTreenode Objekte anhängen
Hallo liebe Community,

ich habe (mal) wieder ein Problem. Und zwar habe ein einen TTreeView-Baum der mit sich dynamisch aufbaut. Nun möchte ich jedoch einige Objekte wie Name, ID, Status, Port anhängen ich habe mich volgendermassen versucht.
TreeView1.Items[i].AddObject(Port, 'Test');

Doch leider funktioniert mein Versuch nicht. Könnte mir einer ein bisschen unter die arme greifen oder hat ein einfaches Tutorial was ich verwenden könnte.

MFG
TIm


Narses - Mi 25.10.06 17:24

Moin!

Schonmal bischen umgesehen? ;) Suche in: Delphi-Forum, Delphi-Library TTREEVIEW

cu
Narses


TimKellner - Mi 25.10.06 21:27

Ok soweit das ich objekte anhängen kann bin ich meiner meinung nach. Das Problem habe ich danke deiner Hilfe so gelöst bekommen. Doch wie bekomme ich die Werte später bei einem ausgewähltem Ast wieder heraus
Auslesen mit

Delphi-Quelltext
1:
tserver(TreeView_List.Selected.Data).Name                    


Erzeugen des Objectes

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
TServer = class(TObject)
  private
    FID: String;
    FName: String;
    FPort: String;
    FStatus: String;
    procedure SetID(const Value: String);
    procedure SetName(const Value: String);
    procedure SetPort(const Value: String);
    procedure SetStatus(const Value: String);
  public
   property ID: String read FID write SetID;
   property Name: String read FName write SetName;
   property Port: String read FPort write SetPort;
   property Status: String read FStatus write SetStatus;
  end;



Delphi-Quelltext
1:
2:
3:
4:
5:
 
fserver.ID := server.Strings[0];
      fserver.Port := server.Strings[1];
      fserver.Name := server.Strings[2];
      fserver.Status := server.Strings[3];


Narses - Mi 25.10.06 22:07

Moin!

Was ist jetzt konkret deine Frage? :gruebel:

cu
Narses


TimKellner - Mi 25.10.06 22:15

Hups. Mein Problem ist wie ich die Data Objecte des ausgewählten Astes auslesen kann


Narses - Mi 25.10.06 22:17

Moin!

Hast du doch schon selbst geschrieben:
user profile iconTimKellner hat folgendes geschrieben:
Auslesen mit

Delphi-Quelltext
1:
tserver(TreeView_List.Selected.Data).Name                    

:D

cu
Narses


TimKellner - Fr 27.10.06 19:46

Ja klar nur er wirft mir eine Exception aus. "Zugriffsverletzung bei Adresse 0048A152 in Modul 'Test.exe'. Lesen von Adresse 00000008"

Deshalb vermute ich das irgendetwas in meinem code nicht stimmt. Nur was im Code falsch ist finde ich nicht herraus.


Narses - Fr 27.10.06 21:04

Moin!

Sieht so aus, als wenn du in .Data NIL stehen hättest. Du mußt da beim Einfügen des Nodes natürlich eine Referenz auf deine Klasseninstanz unterbringen. ;)

cu
Narses


TimKellner - Fr 27.10.06 21:14

Was meinst du damit?

PS: Tut mir leid das ich es nicht so richtig alleine hinbekomme


Narses - Fr 27.10.06 21:18

Moin!

Du erzeugst doch eine Instanz von TServer, die muss in .Data rein. ;)

cu
Narses


TimKellner - Fr 27.10.06 21:23

Verstehe leider immer noch nicht was du meinst. Das ist mein jetztziger Code wo die Exception kommt. Könntest du mir zeigen wie du es meinst.

MFG
TIm


Delphi-Quelltext
1:
2:
3:
4:
procedure TForm_Main.TreeView_listClick(Sender: TObject);
begin
showmessage(tserver(TreeView_List.Selected.Data).Name);
end;


Narses - Sa 28.10.06 00:15

Moin!

Das ist die "falsche" Stelle, hier ist klar, was passiert. "Interessant" ist die Stelle im Code, wo du die Nodes einfügst. ;)

cu
Narses


Coder - Sa 28.10.06 00:29

Edit// Thema verfehlt.
In der VirtualTreeView Hilfe steht das man besser Records als Objekte zum anhängen von Daten verwenden soll.
VirtualTreeview.chm, The virtual paradigm:
Records instead classes
Basically, the idea of virtualizing the tree control and using records instead of classes were two ideas which are born nearly at the same time. It was quite clear from the very first moment that classes can never be as effective as a simple record structures (in terms of size, access speed and management). Sure, a TPersistent only needs 4 bytes more than a record (the pointer to the class' VMT), but these are still too many extra bytes if you consider that I have wrestled quite a while with myself about every byte in a tree node (and want the minimalism principle). Another point you should not underestimate is that classes as nodes would of course also mean to put node specific methods into this class too, which will be overridden at times (this is the main argument to use a class after all). This will require additional CPU cycles just to lookup access methods, to dereference etc. which in turn will cost extra time. Trees with only some 1000 nodes will never see a large difference but for big trees this is significant and Virtual Treeview has mainly been created to address high capacity tree views.

With choosing records I also gave up the VCL concept of having a tree nodes class which is responsible to manage tree nodes and is secondary to the control itself. In Virtual Treeview every access to the tree content is done via methods and properties provided by the tree control. Keep also in mind that nobody prevents you from using classes and store their references in the node's data area. It is only just so that the node (as internal management structure) is as small as possible, opening so all possibilities: from smallest memory footprint to highest comfort.


Darum rat ich dir von den Objekten abzusehen und die einfachere Variante mit Records zu benutzen. :wink:
Hier gibts ein Tutorial dazu: http://www.dsdt.info/tutorials/virtualtreeview/?page=3

MfG


Narses - Sa 28.10.06 00:43

Moin!

user profile iconCoder hat folgendes geschrieben:
In der VirtualTreeView Hilfe steht das man besser Records als Objekte zum anhängen von Daten verwenden soll.
VirtualTreeview.chm, The virtual paradigm:
Records instead classes
Trees with only some 1000 nodes will never see a large difference but for big trees this is significant and Virtual Treeview has mainly been created to address high capacity tree views.

Darum rat ich dir von den Objekten abzusehen und die einfachere Variante mir Records zu benutzen.

Und darum rate ich, sich das nochmal sehr gut zu überlegen; ich kann mir nicht vorstellen, dass records jetzt die entscheidende Lösung bringen.

@user profile iconCoder: Er hat doch keine Performance-Probleme, sondern er kriegt ja nichmal ein Objekt untergebracht. Man kann es auch übertreiben, mit dem Optimieren... ;)

cu
Narses


Coder - Sa 28.10.06 00:49

Edit// Thema verfehlt.
user profile iconNarses hat folgendes geschrieben:
Er hat doch keine Performance-Probleme, sondern er kriegt ja nichmal ein Objekt untergebracht. Man kann es auch übertreiben, mit dem Optimieren... ;)

Mit Rekords ist es aber viiiieeeel einfacher und sie sind im Sinne des Erfinders. :wink:
Naja egal. War nur ein Vorschlag.

MfG


Narses - Sa 28.10.06 00:54

Moin!

user profile iconCoder hat folgendes geschrieben:
Mit Rekords ist es aber viiiieeeel einfacher und sie sind im Sinne des Erfinders.

a) Es ist weder einfacher, noch besser; eher anders. :D
b) Möglicherweise im Sinne des VirtualTreeView-Erfinders, aber das spielt hier ja wohl eher kaum eine Rolle.

cu
Narses


TimKellner - Sa 28.10.06 12:14

ALso meinst du diesen Abschnitt? Wie muss ich diesen verbessern?



Delphi-Quelltext
1:
2:
3:
4:
5:
server.CommaText := response;
fserver.Name := server.Strings[0];
fserver.Data).Port := server.Strings[1];
fserver.Name := server.Strings[2];
fserver.Status := server.Strings[3];


Narses - Sa 28.10.06 20:31

Moin!

Nein, ich meine den Teil im Code, wo du einen neuen Knoten ins TreeView einfügst... ;)

cu
Narses


TimKellner - Sa 28.10.06 21:31

So neuer versuch.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
fserver := TServer.Create;
      server := TStringList.Create;
      try
      server.CommaText := response;
      fserver.Name := server.Strings[0];
      fserver.Data).Port := server.Strings[1];
      fserver.Name := server.Strings[2];
      fserver.Status := server.Strings[3];
      finally
      server.Free;
      TreeView_List.Items.AddChild(node,fserver.Port);


Narses - Sa 28.10.06 21:39

Moin!

Ja schon besser; zeig aber bitte mal noch etwas mehr "drum rum" (konkret: wie kommst du auf "node" als Parameter usw.) ;)

cu
Narses


Coder - Sa 28.10.06 21:46

Edit// Thema verfehlt.
Ich hab VirtualTreeView mal mit Objekten benutzt.
Vielleicht hilft dir das ja weiter:
http://www.delphi-forum.de/viewtopic.php?p=367721#367721

MfG


Narses - Sa 28.10.06 22:11

Moin!

@user profile iconCoder: Sag mal, hat user profile iconTimKellner eigentlich jemals was von VirtualTreeView gesagt... ? :gruebel:

cu
Narses


Coder - Sa 28.10.06 22:15

Edit// Thema verfehlt.
Oh verdammt :autsch:
Wieso hab ich mich schon gewundert? :autsch:
Son mist :autsch:
Ignoriert mich einfach ok? :autsch:
(Ich bin ein Schlauch)


TimKellner - Sa 28.10.06 23:46

Nabend


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
TreeView_List.Items.Clear;
  node := TreeView_list.Items.AddChild(nil,'Übersicht');
  TreeView_List.Items[0].ImageIndex := 9;
  TreeView_List.Items[0].SelectedIndex := 9;
  Form_Login.IdTCPClient1.WriteLn('dbserverlist');
  i := 1;
  repeat
    if i = 1 THEN response := Form_Login.IdTCPClient1.ReadLn;
    response := Form_Login.IdTCPClient1.ReadLn;
    if Response = 'OK' then
    begin
      ende := true;
    end
    else
    begin
      fserver := TServer.Create;
      server := TStringList.Create;
      try
      server.CommaText := response;
      fserver.Name := server.Strings[0];
      fserver.Data).Port := server.Strings[1];
      fserver.Name := server.Strings[2];
      fserver.Status := server.Strings[3];
      finally
      server.Free;
      TreeView_List.Items.AddChild(node,fserver.Port);
      if TreeView_List.Items[i].Level <> 0 THEN
      begin
        if fserver.Status = '1' THEN
        begin
          TreeView_List.Items[i].ImageIndex := 8;
          TreeView_List.Items[i].SelectedIndex := 8;
        end
        else
        begin
          TreeView_List.Items[i].ImageIndex := 7;
          TreeView_List.Items[i].SelectedIndex := 7;
        end;
      end;
    end;


Narses - So 29.10.06 00:01

Moin!

Probier das mal so in der Art:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
  var
    Root, Node: TTreeNode;
    FServer: TServer;
begin
  TreeView_List.Items.Clear;
  Root := TreeView_list.Items.Add(NIL,'Übersicht');
  Root.ImageIndex := 9;
  Root.SelectedIndex := 9;

  FServer := TServer.Create;
  FServer.Name := 'hostname';
  FServer.Port := '1234';
  FServer.Status := '1';
  Node := TreeView_List.Items.AddChild(Root,FServer.Port);
  Node.Data := FServer;

Jetzt hast du eine Referenz auf die Instanz von TServer mit im Knoten und kannst darauf zugreifen. Allerdings darauf achten, dass du entweder die erzeugen Instanzen von TServer irgendwo sammelst und dann später auch wieder freigibst oder das Löschen des TreeViews so erweitern, dass die dranhängenden Objekte auch wieder freigegeben werden. ;)

cu
Narses


Martok - So 29.10.06 00:19

user profile iconNarses hat folgendes geschrieben:

Delphi-Quelltext
1:
2:
  Node := TreeView_List.Items.AddChild(Root,FServer.Port);
  Node.Data := FServer;

Das geht doch kürzer... :gruebel: ... Ahh :idea:

Delphi-Quelltext
1:
  Node := TreeView_List.Items.AddChildObject(Root,FServer.Port,FServer);                    


Narses - So 29.10.06 00:40

Moin!

@user profile iconMartok: Ja, klar geht das kürzer (dann kannst du auch noch das "Node :=" gelassen :idea:), aber macht dann die Technik nicht so schön klar, wie in meiner Version. ;) Und an genau diesem Verständis haperte es ja hier... :D

cu
Narses


Martok - So 29.10.06 00:47

Stimmt.

Mal n bisschen OT: man könnte ja mal einen Wettbewerb machen: ein bestimmtes Problem ist von mehreren Programmierern auf verschiedenen Erfahrungs-Leveln zu lösen. Dann wird der Programmierstil verglichen, und das einfachste, verrückteste usw. prämiert.