Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Problem mit Pointer beim VirtualStringTree (https://www.delphipraxis.net/144292-problem-mit-pointer-beim-virtualstringtree.html)

sirius 4. Dez 2009 12:20

Re: Problem mit Pointer beim VirtualStringTree
 
Das ganze Konzept ist falsch.

Du kannst nicht mehreren Knoten dasselbe Objekt zuweisen.
Baue für jeden Knotentype eine eigene Klasse, welche du von einer abstrakten Klasse ableitest. Die Abstrakte Klasse stellt die einheitliche Schnittstelle für bspw. den NodeText dar.
Speicher die Objekte in einer eigenen Liste und gib diese separat frei, dann brauchst du auch bei OnFreeNode nix zu machen (onFreeNode wird nämlich nicht für jeden Konten immer aufgerufen (siehe MAN))


Edit:
Hier ist ein Besipiel (Beitrag #4).

himitsu 4. Dez 2009 12:28

Re: Problem mit Pointer beim VirtualStringTree
 
Delphi-Quellcode:
pNode := VSTSystem.AddChild(nil,DataSys);
pNode := VSTSystem.AddChild(pNode);
pNode := VSTSystem.AddChild(pNode);
VSTSystem.AddChild(pNode);
Hier wäre nur einem Knoten das Objekt zugewiesen und die untergeordneten Objekte holen sich die Daten dann von dort.


Nocheine Alternative wäre:
man hält die Objekte in einer weiteren Liste, welche diese Objekte verwaltet und später auch freigibt
und er VST bekommt die Objekte in jedem Node zugeordnet, wo er sie braucht, aber der VST sorgt nicht für deren Freigabe.


Zitat:

Zitat von Jens Hartmann
Allerdings, kommt es dann immer genau an der Stelle zu einem Zugriffsfehler, wenn ich den Knoten über Mausklick Erweitern will.

stimmt das mit dem Node auch?
Code:
while TOSYSTEM(VSTSystem.GetNodeData([color=#ff0000][b]p[/b][/color]Node)^) = nil do
    [color=#ff0000][b]p[/b][/color]Node := [color=#ff0000][b]p[/b][/color]Node.ParentNode;

Jens Hartmann 4. Dez 2009 12:42

Re: Problem mit Pointer beim VirtualStringTree
 
Ja, das stimmt. ich habe pNode deklariert.

Delphi-Quellcode:
var
  pNode : PVirtualNode;
  Level: Integer;
  DataSys : TOSYSTEM;  // ein Zeiger auf die Datenstruktur
begin
  Level := VSTSystem.GetNodeLevel(Node);
  while TOSYSTEM(VSTSystem.GetNodeData(pNode)^) = nil do
    pNode := pNode.Parent;
  DataSys := TOSYSTEM(VSTSystem.GetNodeData(Node)^);
  case Level of
  0: case Column of
        0: Celltext := DataSys.Objekt;
      end;
  1: case Column of
        0: Celltext := DataSys.Zentrale;
      end;
  2: case Column of
        0: Celltext := DataSys.IP;
      end;
  3: case Column of
        0: Celltext := DataSys.COM;
      end;
  end;
end;
Ein weiteres Problem, wäre ja auch die Zuordnung von Level 2, ich möchte dem Level mehrer verschieden Einträge zuordnen, die aber im selben Objekt stehen.

siehe DataSys.IP und DataSys.COM

Irgendwie stehe ich momentan total auf der Leitung.
:gruebel:
Gruß Jens

himitsu 4. Dez 2009 12:47

Re: Problem mit Pointer beim VirtualStringTree
 
Code:
v = der tatsächliche Level

0 -Level1
1   -Level2
2     -Level3
[color=#ff0000]2     -Level3[/color]
Code:
var
  Level: Integer;
  DataSys : TOSYSTEM;
begin
  Level := VSTSystem.GetNodeLevel(Node);
  while TOSYSTEM(VSTSystem.GetNodeData(Node)^) = nil do
    Node := Node.Parent;
  DataSys := TOSYSTEM(VSTSystem.GetNodeData(Node)^);
  case Level of
  0: case Column of
        0: Celltext := DataSys.Objekt;
      end;
  1: case Column of
        0: Celltext := DataSys.Zentrale;
      end;
  2: case Column of
        0: Celltext := DataSys.IP;
      end;
  [color=#ff0000]3: case Column of
        0: Celltext := DataSys.COM;
      end;[/color]
  end;
end;
oder
Code:
var
  [color=#0000ff][b]p[/b][/color]Node: PVirtualNode;
  Level: Integer;
  DataSys : TOSYSTEM;
begin
  [color=#0000ff][b]p[/b][/color]Node := Node;
  Level := VSTSystem.GetNodeLevel([color=#0000ff][b]p[/b][/color]Node);
  while TOSYSTEM(VSTSystem.GetNodeData([color=#0000ff][b]p[/b][/color]Node)^) = nil do
    [color=#0000ff][b]p[/b][/color]Node := [color=#0000ff][b]p[/b][/color]Node.Parent;
  DataSys := TOSYSTEM(VSTSystem.GetNodeData([color=#0000ff][b]p[/b][/color]Node)^);
  case Level of
  0: case Column of
        0: Celltext := DataSys.Objekt;
      end;
  1: case Column of
        0: Celltext := DataSys.Zentrale;
      end;
  2: case Column of
        0: Celltext := DataSys.IP;
      end;
  [color=#ff0000]3: case Column of
        0: Celltext := DataSys.COM;
      end;[/color]
  end;
end;

Jens Hartmann 4. Dez 2009 13:01

Re: Problem mit Pointer beim VirtualStringTree
 
Das mit dem Level3 ist mir klar.

Delphi-Quellcode:
  2: case Column of
        0: Celltext := DataSys.IP;
      end;
  3: case Column of
        0: Celltext := DataSys.COM;
      end;
  end;
Allerdings, wie füge ich die dann direkt hintereinander ein. Weil ich kann ja schlecht schreiben

Delphi-Quellcode:
  3: case Column of
        0: Celltext := DataSys.COM;
        0: Celltext := DataSys.IP;
      end;
  end;

himitsu 4. Dez 2009 13:40

Re: Problem mit Pointer beim VirtualStringTree
 
tja, das ist halt ein Problem in deiner Implementierung.

Wenn alles in einer Struktur stehen soll, dann brauchst du eine zuverlässige Methode die Nodes zu unterscheiden.

Kann man eigentlich einen Index erhalten? (also der wievielte SubNode es innerhalb des Eltern-Knotens ist?)

Delphi-Quellcode:
var
  Level, Index: Integer;
  DataSys : TOSYSTEM;
begin
  Level := VSTSystem.GetNodeLevel(Node);
  Index := VSTSystem.GetNodeIndex(Node); // oder irgendwie so, aber
  // nicht der globale Index, sondern nur der im Verhältnis zum Parent-Node
  while TOSYSTEM(VSTSystem.GetNodeData(Node)^) = nil do
    Node := Node.Parent;
  DataSys := TOSYSTEM(VSTSystem.GetNodeData(Node)^);
  case Level of
  0: case Column of
        0: Celltext := DataSys.Objekt;
      end;
  1: case Column of
        0: Celltext := DataSys.Zentrale;
      end;
  2: case Index of
        0: case Column of
             0: Celltext := DataSys.IP;
           end;
        1: case Column of
             0: Celltext := DataSys.COM;
           end;
      end;
  end;
end;
Aber so ist es schwer mal etwas einzufügen oder zu ändern, da diese Indize ganz genau mit der Erstellung abhängen.
Wenn man da was einfügt, dann muß man es auch überll ändern, sonst gibt es Probleme.

Also einfacher wäre es, wenn du

- entweder für jeden Node ein eigenes Objekt erstellt, so nur die zugehörige Info drinsteht

- oder du nutzt ein Trägerobjekt
also ein Objekt, wo du dein TOSYSTEM drin ablegst und welches entweder ein Feld "Text" hat, welches für die Anzeige genutzt wird
oder wo zumindestens gespeichert wird, welche Wert des TOSYSTEM nun in genau diesem Node angezeigt werden soll.

Jens Hartmann 4. Dez 2009 14:24

Re: Problem mit Pointer beim VirtualStringTree
 
Das wäre möglich.

Den Anfang dafür hatte ich auch schon mal..

Delphi-Quellcode:
  TOOBJEKT = class
    private
      Objekt    : String;
      ImageIndex : Integer;
  end;

  TOSYSTEM = class
    private
      Zentrale    : String;
      ImageIndex : Integer;
  end;

  TODATASYS = class
    private
      COM, IP    : String;
      ImageIndex : Integer;
  end;
Aber wie kann ich dann die Größe von NodeDataSize festlegen...

Delphi-Quellcode:
  VSTSystem.NodeDataSize := SizeOf(TOSYSTEM);
Gruß Jens

Jens Hartmann 4. Dez 2009 14:48

Re: Problem mit Pointer beim VirtualStringTree
 
Es kann ja auch eigendlich nicht so schwer sein, es ist ja vom Prinzip her nichts anderes als ein Explorer.

Da gibt es ja auch solche Herachien...

Code:
Level 1
  - Level 2
  - Level 2
    - Level3
  - Level 2
    - Level 3
    - Level 3

etc....
Das Problem, was ich sehe, ich habe schon viele Tutorials gelesen, in dennen man diese Struktur erstellen kann. Aber noch nicht herausgefunden, wie man dann die Daten zuweisen tut.

Gruß Jens

Jens Hartmann 4. Dez 2009 15:12

Re: Problem mit Pointer beim VirtualStringTree
 
Ich habe jetzt hier mal noch den gesamten aktuelle Code der das VST Betrifft.

Vieleicht hilt das ja weiter. Irgendwie glaube ich, ist da noch ein Gedankenfehler von mir drin...

Delphi-Quellcode:
//Die OBJEKTE
  TOOBJEKT = class
    private
      Objekt    : String;
      ImageIndex : Integer;
  end;

  type TOSYSTEM = class
    private
      Zentrale    : String;
      ImageIndex : Integer;
    end;


  TODATASYS = class
    private
      COM, IP    : String;
      ImageIndex : Integer;
  end;
//im FormCreate
VSTSystem.NodeDataSize := SizeOf(TOSYSTEM); //Aber ja Vermutlich nicht ganz richtig, da ich ja mehrere Objekte zur Zeit nutze.
VSTSystemCreate;

//Durch FormCreate aufgerufen
procedure TForm1.VSTSystemCreate;
var
  DataObj : TOOBJEKT;
  DataSys : TOSYSTEM;
  Data    : TODATASYS;
  pNode :pVirtualNode; // ein Pointer auf Knoten
  i : integer;
begin
  DM_PS.ConPSConfig.Connect;
  DM_PS.Qry_VSTSystemCreate.Open;

  DataObj := TOOBJEKT.Create;
  DataSys := TOSYSTEM.Create;
  Data   := TODATASYS.Create;

  VSTSystem.BeginUpdate;

  DataObj.Objekt := DM_PS.Qry_VSTSystemCreate.FieldByName('KUNDE').AsString;

  case DM_PS.Qry_VSTSystemCreate.FieldByName('ZENTRALENTYP').AsInteger of
        0: DataSys.Zentrale := 'NOVAR HB/MB 24';
        1: DataSys.Zentrale := 'NOVAR HB/MB 48';
        2: DataSys.Zentrale := 'NOVAR MB100';
        3: DataSys.Zentrale := 'NOVAR MB256';
        4: DataSys.Zentrale := 'BOSCH UEZ2000';
        5: DataSys.Zentrale := 'NOVAR BMC 1024';
        6: DataSys.Zentrale := 'ESSER IQ8 Control';
        7: DataSys.Zentrale := 'SONSTIGE';
      end;

  Data.COM := 'COM 1, 9600,8,1';
  Data.IP := '192.168.100.101';

  pNode := VSTSystem.AddChild(nil,DataObj);
  pNode := VSTSystem.AddChild(pNode,DataSys);
  pNode := VSTSystem.AddChild(pNode,Data);

  VSTSystem.EndUpdate;
  VSTSystem.Refresh;
end;

//Ereignisse vom VST
procedure TForm1.VSTSystemFreeNode(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
var
  DataObj : TOOBJEKT;
  DataSys : TOSYSTEM;
  Data   : TODATASYS;
begin
  DataObj := TOOBJEKT(VSTSystem.GetNodeData(Node)^);
  DataObj.Free;
  DataSys := TOSYSTEM(VSTSystem.GetNodeData(Node)^);
  DataSys.Free;
  Data := TODATASYS(VSTSystem.GetNodeData(Node)^);
  Data.Free;
end;


procedure TForm1.VSTSystemGetImageIndex(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
  var Ghosted: Boolean; var ImageIndex: Integer);
begin
  case Sender.GetNodeLevel(Node) of
    0: ImageIndex := 0;
    else ImageIndex := -1;
  end;
end;

procedure TForm1.VSTSystemGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
  pNode: PVirtualNode;
  Level, Index: Integer;
  DataObj : TOOBJEKT;
  DataSys : TOSYSTEM;
  Data   : TODATASYS;
begin
  DataObj := TOOBJEKT(VSTSystem.GetNodeData(Node)^);
  DataSys := TOSYSTEM(VSTSystem.GetNodeData(Node)^);
  Data   := TODATASYS(VSTSystem.GetNodeData(Node)^);

  Level := VSTSystem.GetNodeLevel(Node);

  case Level of
    0: Celltext := DataObj.Objekt;
    1: Celltext := DataSys.Zentrale;
    2: Celltext := Data.COM;
  end;
end;
Ich hoffe das hilft weiter.

Danke schon mal

Gruß Jens

Jens Hartmann 5. Dez 2009 18:00

Re: Problem mit Pointer beim VirtualStringTree
 
Hallo zusammen,

hat den keiner irgendeinen Tip. Vieleicht noch als Hinweis.

Ich habe eine Datenbank, in der mehrere Tabellen existieren. Ich möchte diese im VST anzeigen. Und zwar in folgender Darstellung...

Code:
-Tabelle 1
  -Inhalt Spalte 1
  -Inhalt Spalte 2
  -Inhalt Spalte 3
  -Inhalt Spalte 4
-Tabelle 2
  -Inhalt Spalte 1
    -Wert 1
    -Wert 2
    -Wert 3
  -Inhalt Spalte 2
    -Wert 1
    -Wert 2
    -Wert 3
  -Inhalt Spalte 3
    -Wert 1
    -Wert 2
    -Wert 3
Bin leider noch kein Stück weiter gekommen.

Danke schon mal

Gruß Jens


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:02 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz