Delphi-PRAXiS

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 .... nochmals VirtualStringTree (https://www.delphipraxis.net/31342-nochmals-virtualstringtree.html)

marcus 7. Okt 2004 17:37


.... nochmals VirtualStringTree
 
Hallo zusammen,

ich kämpfe mal wieder mit der VirtualStringTree-Komponente. :wall:
Bis jetzt funktioniert die Darstellung ohne Childnodes und das Prinzip der VirtualStringTree ist mir, glaube ich, auch klar (Trennung von Struktur und Inhalt- grob gesagt).
Für eine einzeilig Node habe ich einen einfachen Record, der ungefähr so aussieht:

Delphi-Quellcode:
type
  tVSTData = record
  String1 : String;
  String2 : String;
  Zahl3   : Integer;
end;
Wenn ich jetzt aber eine ChildNode hinzufügen will, wie schaut dann der Record aus? Muss ich einfach eine zusätzliche Variable vom Typ PVirtualNode dem Record hinzufügen?

Gruß
Marcus

phXql 7. Okt 2004 19:01

Re: .... nochmals VirtualStringTree
 
nö. du machst einfach node := VST1.addchild(nil); (das is der root). dann machst du VST1.AddChild(Node); // Das is dann das child zu dem root. den record musst du nich ändern..

Dezipaitor 7. Okt 2004 21:11

Re: .... nochmals VirtualStringTree
 
Delphi-Quellcode:
type
  tVSTData = record
  String1 : String;
  String2 : String;
  Zahl3   : Integer;
end;
zuallererst : Es fehlt ein Pointer auf die Struktur:
Delphi-Quellcode:
PVSTData = ^tVSTData;
Dann musst du der VirtualTree Komponente sagen, wie groß die Struktur ist :

Delphi-Quellcode:
YourVTree.NodeDataSize := SizeOf(tVSTData);
Dann kannst du einfügen
Delphi-Quellcode:
var Node : PVirtualNode;
    Data : PVSTData;
begin
  Node := YourVTree.AddChild(nil);

  Data := YourVTree.GetNodeData(Node);

  Data^.String1 := '123';
  ..
end;
das machst du immer so, wenn du was lesen oder ändern willst

marcus 8. Okt 2004 08:48

Re: .... nochmals VirtualStringTree
 
Hallo,

okay, das ist klar. Ich hab nur noch momentan ein Problem mit dem Verständnis bei unterschiedlichen Strukturen für die RootNode und die ChildNodes. Folgende Struktur mal angenommen:

Delphi-Quellcode:
+ Monat
  + Kalenderwoche
    - Projektnummer, Projektname, Datum
        .
        .
        .
Wenn ich jetzt die Projektdaten hinzufüge und einen Record habe der so ausschaut:

Delphi-Quellcode:
type
  tVSTData = record
  Monat          : String;
  Kalenderwoche  : String;
  Projektnummer  : Integer;
  Projektname    : String;
  Datum          : TDateTime;
end;
dann wird doch für jedes Projekt, welches ich hinzufüge, eine RootNode Monat und Kalenderwoche hinzugefügt?

Gruß
Marcus

Igotcha 8. Okt 2004 09:01

Re: .... nochmals VirtualStringTree
 
Nein, Du hast eigentlich kein Verständnisproblem, denn die Struktur von Root- und Childnodes muss identisch sein.

Du kannst einem Root-Node nicht z.B. geben:

|ID|Monate

und dem Child

|ID|Monate|Tage

Allen Nodes im VT liegt die selbe Recordstruktur zugrunde (ob Du sie mit Daten füllst, ist Deine Sache).

In Deinem Beispiel hätte der VT dann 5 Spalten:

Monat|Kalenderwoche|Projektnummer|Projektname|Datu m

Gruß Igotcha

P.S. Was Du machen könntest, kannst Du hier auf dem Screenshot sehen (von meiner Anwendung)Bild. Du könntest, wo bei mir BEZEICHNUNG steht, z.B. ZEITRAUM schreiben und dann nach JAHR/MONAT Root und Childs bilden, dafür musst Du aber Deine Datenstruktur grundlegend anpassen und eine Parent/Child-Relation hinterlegen

Dein Record könnte dann z.B. so aussehen:

Delphi-Quellcode:
type
PVSTData = ^TVSTData;
TVSTData = record
strPeriode: String;
iProjektnummer: Integer;
strProjektname: String;
dDatum: TDateTime;
strParentID: String;
end;
Deine Records könnten nun so aussehen:

Code:
PERIODE     PROJEKTNR PROJEKTNAME DATUM     PARENTID
10/2004      NULL     NULL       NULL      0
42           12345     Test       11.10.2004 10/2004
42           45678     Test2       13.10.2004 10/2004
11/2004      NULL     NULL       NULL      0
45           78901     Test3       01.11.2004 11/2004
Wenn Du jetzt z.B. aus der DB auslesen willst, machst Du ein

SELECT * FROM tabelle ORDER BY PARENTID, KW, DATUM

liest alles in einer Schleife ein und abhängig von PARENTID erstellst Du einen Rootnode oder einen passenden Childnode zur PARENTID.

marcus 8. Okt 2004 09:14

Re: .... nochmals VirtualStringTree
 
:gruebel:
also wenn ich Monat und Kalenderwoche(um das vorherige Beispiel aufzugreifen) nichts zuweise, und eine Node anlege dann werden die "Einträge" des Records die Leer sind nicht angezeigt?

Wenn das so ist, dann wird es natürlich schon etwas klarer. Denn bei den Beispielen habe ich immer nach den Strukturen der Nodes gesucht und es war mir nie klar wie zwischen den einzelnen Nodes (Root,Child) unterschieden wird. Die Unterscheidung findet also nur in der "Befüllung" meines Records/Objects statt?

Gruß
Marcus

Igotcha 8. Okt 2004 09:23

Re: .... nochmals VirtualStringTree
 
Schau Dir mal mal meinen editierten Post an.

Igotcha 8. Okt 2004 09:32

Re: .... nochmals VirtualStringTree
 
EDIT: Ich habe meine Beispielstruktur editiert, da sie murks war ;-) Du musst nur darauf achten, dass Du Dir irgendwie eine eindeutige PARENTID bastelst (evtl. Nimmst Du noch das Jahr mit rein beim Monat) - mein Beispiel ist nicht eindeutig, da es MONAT=11 und KW=11 geben kann, also für die Spalte ZEITRAUM. Besser, Du schreibst beim Monat noch das Jahr dazu.

Du wirst dabei aber auf ein grundsätzliches "Problem" bei der Arbeit mit VTs stossen, denn man kann Nodes dort nicht direkt anspringen. Sprich sowas wie "hänge den Child an den Node 123" gibt es von Hause aus nicht.

Da kannst Du Dir eine Funktion zu schreiben:

Delphi-Quellcode:
function TfrmMain.FindNodeByPERIODE(aTree: TBaseVirtualTree;
  aID: String;): PVirtualNode;
var
   NodeData: pVSTData;
begin
   Result := aTree.GetFirst;
   while Assigned(Result) do
   begin
     NodeData := pVSTData(aTree.GetNodeData(Result));
     if NodeData^.strPeriode=aID Then
       Exit;
     Result := aTree.GetNext(Result);
   end;
end;
Wenn Du also in Deiner Schleife auf einen Eintrag stößt, wo PARENTID <> 0 ist, dann rufst Du auf:

Code:
 
var
aktueller_knoten: PVirtualNode;
myData: PVSTData;
begin
<--- SCHLEIFENAUSZUG
<--- dieses Konstrukt musst Du in der Schleife für Childs verwenden
aktueller_knoten:=DEINVST.AddChild( FindNodebyPERIODE(DEINVST, PARENTID));
myData:=DEINVST.GetNodeData(aktueller_knoten);
myData.strPeriode:=inttostr(42); //KALENDERWOCHE
myData.strProjektname:='Test';
etc.
end;
Und das Child wird an den richtigen Root angehängt.

Beim Arbeiten mit VSTs muss man sich erstmal bewußt werden, dass dieser wirklich nichts anderes macht, als spitzenmäßige Visualisierungsmöglichkeiten für Treeview-artige Strukturen zu ermöglichen - die Datenhaltung musst Du selbst machen.

Gruß Igotcha

marcus 8. Okt 2004 09:49

Re: .... nochmals VirtualStringTree
 
Wow! Vielen Dank, das hilft mir schon ziemlich weit.
Heute Nachmittag nach der Arbeit wird das erst mal ausprobiert :D
VirtualStringTree ist schon eine recht komplexe Komponente, und da erst mal einen Überblick zu bekommen und die Grundlegenden Sachen zu verstehen dauert schon ein weilchen.

Gruß
Marcus

phXql 8. Okt 2004 15:20

Re: .... nochmals VirtualStringTree
 
ich find den VST nur noch genial :D

generic 8. Okt 2004 22:56

Re: .... nochmals VirtualStringTree
 
wie waere es mit sowas:

Delphi-Quellcode:
vst.nodedatasize:=sizeof(tobject)

type
  tmonat = class
    a,b: string;
    c: integer;
  end;
  twoche = class
    d: integer;
  end;
  tprojekt = class
    name, usw: string;
  end;

 
  monat:=tmonat.create();
 
  node:=vst.addchild(nil, monat);

  woche:=twoche.create();
  node:=vst.addchild(node, woche);

  proj:=tprojekt.Create();
  vst.addchild(node, proj);


procedure vst.onfreenode
  tobject(vst.getnodedata(node)).free;


procedure vst.ongettext;

obj:=tobject(vst.getnodedata(node));
if obj is tmonat then
  with tmonat(obj) do
    case column of
      0: celltext:=a;
      1: celltext:=b;
    end;

if obj is twoche then
  with twoche (obj) do
    case column of
      0: celltext:=d;
    end;

if obj is tproject then
  with tproject(obj) do
    case column of
      0: celltext:=name;
      1: celltext:=usw;
    end;

marcus 14. Okt 2004 07:55

Re: .... nochmals VirtualStringTree
 
Sodala, funktioniert eigentlich schon ganz gut, bis auf das "füllen" der ChildNodes.
Hier mal der Code

Delphi-Quellcode:
type
PVSTData = ^TVSTData;
TVSTData = record
  monat: string;
  projektnr: string;
end;


procedure TFrmMain.InitForm;
var count               : integer;
    strMonths           : string;
    actMonth,actYear,foo : word;
    result              : pmysql_res;
    row                 : pmysql_row;
    rowCount            : my_ulonglong;
    rootNode,childNode  : PVirtualNode;
    rootData,childData  : PVSTData;
begin
  .
  .
  .

  StringTree.BeginUpdate;
  StringTree.NodeDataSize := SizeOf(PVSTData);

  for count := 1 to CMONTHS do
  begin
    rootNode := StringTree.AddChild(nil);
    rootData := StringTree.GetNodeData(rootNode);
    rootData^.monat := CboxMonth.Items.Strings[count - 1];

    Query('SELECT p_nummer FROM projekte WHERE (p_monat = '+inttostr(count)+')');
    result := mysql_store_result(SqlHnd);
    rowCount := mysql_num_rows(result);
    while (rowCount > 0) do
    begin
      row := mysql_fetch_row(result);
      childNode := StringTree.AddChild(rootNode);
      childData := StringTree.GetNodeData(childNode);
  --> childData^.projektnr := row[0];
      //showmessage(row[0]);
      dec(rowCount);
    end;
    mysql_free_result(result);
  end;
  StringTree.EndUpdate;
end;

Wenn die Zeile mit Pfeil auskommentiert wird dann funktioniert das ganze wunderbar. Es werden alle 12 Monate angelegt und für jeden Monat wird auch die richtige Anzahl an ChildNodes entsprechend den Projekten in dem jeweiligen Monat angelegt. Nur wenn ich die Projektnummer auch anzeigen möchte in dem VirtualStringTree, dann gibts eine AccessViolation. An dem MySQL Ergebnis liegt es nicht, denn die Nummer kann ich mir mit showmessage anzeigen lassen. Ich habe auch mal versucht in den gleichen Record zu schreiben (rootData), hat auch nicht funktioniert.

Marcus

CenBells 14. Okt 2004 09:02

Re: .... nochmals VirtualStringTree
 
Zitat:

Zitat von marcus
Wenn die Zeile mit Pfeil auskommentiert wird dann funktioniert das ganze wunderbar. Es werden alle 12 Monate angelegt und für jeden Monat wird auch die richtige Anzahl an ChildNodes entsprechend den Projekten in dem jeweiligen Monat angelegt. Nur wenn ich die Projektnummer auch anzeigen möchte in dem VirtualStringTree, dann gibts eine AccessViolation. An dem MySQL Ergebnis liegt es nicht, denn die Nummer kann ich mir mit showmessage anzeigen lassen. Ich habe auch mal versucht in den gleichen Record zu schreiben (rootData), hat auch nicht funktioniert.

Hi,

wie sieht denn dein ongettext aus?

Gruß
Ken

marcus 14. Okt 2004 09:17

Re: .... nochmals VirtualStringTree
 
Hallo, der geht natürlich auch in die Hose.

Delphi-Quellcode:
procedure TFrmMain.StringTreeGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: WideString);
var Data : PVSTData;
begin
  Data := Sender.GetNodeData(Node);

  if Node.Parent = Sender.RootNode then
    CellText := Data^.monat
  else
    CellText := Data^.projektnr;
    //CellText := 'test';
end;

generic 14. Okt 2004 10:39

Re: .... nochmals VirtualStringTree
 
imho liegt das an pmysql_row.
das p deutet auf einen zeiger.

probier mal
Delphi-Quellcode:
var s: string;

s:=strpas(row[0])
childData^.projektnr := s;

Gruber_Hans_12345 14. Okt 2004 10:49

Re: .... nochmals VirtualStringTree
 
ich glaub, das es es eher an
Delphi-Quellcode:
StringTree.NodeDataSize := SizeOf(PVSTData);
liegt, da du VST die allokierung (man wie schreibt man das auf Deutsch ?) des Speichers an VST übergibst.

und die sagst im ja nur die größe des Pointers !

probier mal
Delphi-Quellcode:
StringTree.NodeDataSize := SizeOf(TVSTData);
gruss
hans

marcus 14. Okt 2004 11:57

Re: .... nochmals VirtualStringTree
 
Tatsache,

funktioniert wunderbar!

Vielen Dank
Marcus


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:37 Uhr.

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