AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TVirtualStringTree mit TObjectList

Ein Thema von lowmax_5 · begonnen am 28. Feb 2019 · letzter Beitrag vom 1. Mär 2019
Antwort Antwort
Seite 1 von 2  1 2      
lowmax_5

Registriert seit: 9. Mai 2003
Ort: Münster, NRW
258 Beiträge
 
Delphi 11 Alexandria
 
#1

TVirtualStringTree mit TObjectList

  Alt 28. Feb 2019, 23:57
Hallo,

ich stehe grad etwas auf dem Schlauch:
Ich möchte in einem TVirtualStringTree eine TObjectList anzeigen lassen die in etwa so aussieht:

Zeitraum Spalte1 Spalte2 Spalte 3
01/2019
==> Zeile1 Wert1 Wert2 Wert3
==> Zeile2 Wert3 Wert4 Wert5

02/2019
==> Zeile1 Wert6 Wert7 Wert8
==> Zeile9 Wert10 Wert11 Wert12


Als Ergebnis kommt aber nur folgendes raus:

Zeitraum Spalte1 Spalte2 Spalte 3
01/2019
==> Zeile1 Wert1 Wert2 Wert3
==> Zeile2 Wert3 Wert4 Wert5

02/2019
==> Node Node Node Node
==> Node Node Node Node

Was läuft das falsch? Wird das Object korrekt an ..GetText übergeben?


Die Objectlist ist wie folgt definiert:

Code:
unit uMyTypes;

interface

uses System.Classes,System.Generics.Collections;

type

  TDetailClass = class
   private
    FWert1: String;
    FCaption: String;
    FWert2: String;
    FWert3: String;
    procedure SetCaption(const Value: String);
    procedure SetWert1(const Value: String);
    procedure SetWert2(const Value: String);
    procedure SetWert3(const Value: String);
   public
    property Caption: String read FCaption write SetCaption;
    property Wert1: String read FWert1 write SetWert1;
    property Wert2: String read FWert2 write SetWert2;
    property Wert3: String read FWert3 write SetWert3;
  end;

  TDataClass = class
    private
    FZeitraum: String;
    FDetail1: TDetailClass;
    FDetail2: TDetailClass;
    procedure SetZeitraum(const Value: String);
    procedure SetDetail1(const Value: TDetailClass);
    procedure SetDetail2(const Value: TDetailClass);
    public
    constructor Create;
    destructor destroy;
    property Zeitraum: String read FZeitraum write SetZeitraum;
    property Detail1: TDetailClass read FDetail1 write SetDetail1;
    property Detail2: TDetailClass read FDetail2 write SetDetail2;
  end;

  PDataClass = ^TDataClass;

  TDataLst = TObjectList<TDataClass>;

implementation

{ TDetail }

procedure TDetailClass.SetCaption(const Value: String);
begin
  FCaption := Value;
end;

procedure TDetailClass.SetWert1(const Value: String);
begin
  FWert1 := Value;
end;

procedure TDetailClass.SetWert2(const Value: String);
begin
  FWert2 := Value;
end;

procedure TDetailClass.SetWert3(const Value: String);
begin
  FWert3 := Value;
end;

{ TData }



constructor TDataClass.Create;
begin
    FDetail1 := TDetailClass.Create;
    FDetail2 := TDetailClass.Create;
end;

destructor TDataClass.destroy;
begin
  FDetail1.Free;
  FDetail2.Free;
end;

procedure TDataClass.SetDetail1(const Value: TDetailClass);
begin
  FDetail1 := Value;
end;

procedure TDataClass.SetDetail2(const Value: TDetailClass);
begin
  FDetail2 := Value;
end;

procedure TDataClass.SetZeitraum(const Value: String);
begin
  FZeitraum := value;
end;


end.








Code:
procedure TForm5.Button10Click(Sender: TObject);
var
  vtc: TVirtualTreeColumn;
  vnHead: PVirtualNode;
  I: Integer;
  Data: TDataClass;
begin
  vstSP.Header.Options := vstSP.Header.Options + [hoVisible];


  vtc:= vstSP.Header.Columns.Add;
  vtc.Text:= 'Zeitraum';
  vtc.Width := 150;

  vtc:= vstSP.Header.Columns.Add;
  vtc.Text:= 'Wert1';
  vtc.Width := 100;

  vtc:= vstSP.Header.Columns.Add;
  vtc.Text:= 'Wert2';
  vtc.Width := 100;

  vtc:= vstSP.Header.Columns.Add;
  vtc.Text:= 'Wert3';
  vtc.Width := 100;


  vstSP.NodeDataSize:=SizeOf(TDataClass);

  vstSP.BeginUpdate;

  Data := TDataClass.Create;
  DataLst.Add(Data);
  Data.Zeitraum := '01/2019';
  vnHead:= AddVSTStructureHeadClass(vstSP, nil, TDataClass(DataLst[0]));

  Data.Detail1.Caption:='Zeile1:';
  Data.Detail1.Wert1 := 'Det1 - Wert1';
  Data.Detail1.Wert2 := 'Det1 - Wert2';
  Data.Detail1.Wert3 := 'Det1 - Wert3';
  AddVSTStructureDetailClass(vstSP, vnHead, TDataClass(DataLst[0]));

  Data.Detail2.Caption:='Zeile2:';
  Data.Detail2.Wert1 := 'Det2 - Wert1';
  Data.Detail2.Wert2 := 'Det2 - Wert2';
  Data.Detail2.Wert3 := 'Det2 - Wert3';
  AddVSTStructureDetailClass(vstSP, vnHead, TDataClass(DataLst[0]));



  //Daten Fuellen2
  Data := TDataClass.Create;
  DataLst.Add(Data);
  Data.Zeitraum := '02/2019';
  vnHead:= AddVSTStructureHeadClass(vstSP, nil, TDataClass(DataLst[1]));


  Data.Detail1.Caption:='Zeile1:';
  Data.Detail1.Wert1 := 'Det3 - Wert1';
  Data.Detail1.Wert2 := 'Det3 - Wert2';
  Data.Detail1.Wert3 := 'Det3 - Wert3';
  AddVSTStructureDetailClass(vstSP, vnHead, TDataClass(DataLst[1]));

  Data.Detail2.Caption:='Zeile2:';
  Data.Detail2.Wert1 := 'Det4 - Wert1';
  Data.Detail2.Wert2 := 'Det4 - Wert2';
  Data.Detail2.Wert3 := 'Det4 - Wert3';
  AddVSTStructureDetailClass(vstSP, vnHead, TDataClass(DataLst[1]));

  vstSP.EndUpdate;

  vstSP.FullExpand;

end;



procedure TForm5.vstSPFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
  Data: PDataClass;
begin
  Data := vstSP.GetNodeData(Node);
  if Assigned(Data) then
  begin
    Data := nil;
  end;
end;


procedure TForm5.vstSPGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  Data: PDataClass;

begin
  Data := vstSP.GetNodeData(Node);


  if vstSP.GetNodeLevel(Node)=0 then
  //if Node.Index=0 then
  begin
    case Column of
      0: CellText := Data.Zeitraum;
      1: CellText := '';
      2: CellText := '';
      3: CellText := '';
    end;
  end;

 if vstSP.GetNodeLevel(Node)=1 then
 //if Node.Index=1 then
  begin
    if vstSP.AbsoluteIndex(Node)=1 then
    begin
      case Column of
        0: CellText := Data.Detail1.Caption;
        1: CellText := Data.Detail1.Wert1;
        2: CellText := Data.Detail1.Wert2;
        3: CellText := Data.Detail1.Wert3;
      end;
    end;

    if vstSP.AbsoluteIndex(Node)=2 then
  //  if Node.Index=2 then
    begin
      case Column of
        0: CellText := Data.Detail2.Caption;
        1: CellText := Data.Detail2.Wert1;
        2: CellText := Data.Detail2.Wert2;
        3: CellText := Data.Detail2.Wert3;
      end;
    end;

  end;



end;
  Mit Zitat antworten Zitat
bcvs

Registriert seit: 16. Jun 2011
703 Beiträge
 
Delphi 12 Athens
 
#2

AW: TVirtualStringTree mit TObjectList

  Alt 1. Mär 2019, 08:24
Jeder Node des Vst sollte sein eigenes Data-Objekt haben.

Dann kannst du auch auf die Unterscheidung Detail1 und Detail2 verzeichten und hast einfach nur noch Detail.

Im GetText kannst du dann bei NodeLevel = 1 einfach die Werte des Data-Objekts des jeweiligen Nodes ausgeben und musst nicht auf AbsoluteIndex prüfen. Das funktioniert hier nämlich nicht so, wie du dir das vorgestellt hast. Die beiden letzten Detailzeiten wären AbsoluteIndex 4 und 5.
  Mit Zitat antworten Zitat
lowmax_5

Registriert seit: 9. Mai 2003
Ort: Münster, NRW
258 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: TVirtualStringTree mit TObjectList

  Alt 1. Mär 2019, 09:50
Vielen Dank für die Hilfe!

Zitat:
Im GetText kannst du dann bei NodeLevel = 1 einfach die Werte des Data-Objekts des jeweiligen Nodes ausgeben und musst nicht auf AbsoluteIndex prüfen. Das funktioniert hier nämlich nicht so, wie du dir das vorgestellt hast. Die beiden letzten Detailzeiten wären AbsoluteIndex 4 und 5.
Hier hatte ich einen Gedankenfehler. Ist nun natürlich logisch...


Aktuell hakt es nur beim zweiten Child. Wie bekomme ich da unterschiedliche Daten im zweiten Child angezeigt?
Ich hatte bereits auf ein Detail zurückgebaut und AbsoluteIndex entfernt...
  Mit Zitat antworten Zitat
Benutzerbild von ConnorMcLeod
ConnorMcLeod

Registriert seit: 13. Okt 2010
Ort: Bayern
490 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: TVirtualStringTree mit TObjectList

  Alt 1. Mär 2019, 10:03
Vllt hakt es noch am Verständnis, wie GetText aufgerufen wird? Nämlich für jeden Node extra. Es ist nicht notwendig, alle Nodes in der Funktion abzuarbeiten...
Nr.1 Delphi-Tool: [F7]
  Mit Zitat antworten Zitat
lowmax_5

Registriert seit: 9. Mai 2003
Ort: Münster, NRW
258 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: TVirtualStringTree mit TObjectList

  Alt 1. Mär 2019, 10:29
Aktuell fülle ich die Struktur mit:


Code:
  Data := TDataClass.Create;
  DataLst.Add(Data);
  Data.Zeitraum := '01/2019';
  vnHead:= AddVSTStructureHeadClass(vstSP, nil, TDataClass(DataLst[0]));

  Data.Detail.Caption:='Zeile1:';
  Data.Detail.Wert1 := 'Det1 - Wert1';
  Data.Detail.Wert2 := 'Det1 - Wert2';
  Data.Detail.Wert3 := 'Det1 - Wert3';
  AddVSTStructureDetailClass(vstSP, vnHead, DataLst[0].Detail);

  Data.Detail.Caption:='Zeile2:';
  Data.Detail.Wert1 := 'Det2 - Wert1';
  Data.Detail.Wert2 := 'Det2 - Wert2';
  Data.Detail.Wert3 := 'Det2 - Wert3';
  AddVSTStructureDetailClass(vstSP, vnHead, DataLst[0].Detail);

GetText:

Code:
procedure TForm5.vstSPGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  Data: PDataClass;
  Detail : PDetailClass;

begin
      Detail := vstSP.GetNodeData(Node);

  if vstSP.GetNodeLevel(Node)=0 then
  begin
    Data := vstSP.GetNodeData(Node);
     Data := vstSP.GetNodeData(Node);
    case Column of
      0: begin
           CellText := Data.Zeitraum;
         end;
      1: CellText := '';
      2: CellText := '';
      3: CellText := '';
    end;
  end;

 if vstSP.GetNodeLevel(Node)=1 then
 begin
      case Column of
        0: CellText := Detail.Caption;
        1: CellText := Detail.Wert1;
        2: CellText := Detail.Wert2;
        3: CellText := Detail.Wert3;
      end;

    end;
end;


Im Ergebnis wird für beide Childs nur Zeile 2 angezeigt
  Mit Zitat antworten Zitat
bcvs

Registriert seit: 16. Jun 2011
703 Beiträge
 
Delphi 12 Athens
 
#6

AW: TVirtualStringTree mit TObjectList

  Alt 1. Mär 2019, 10:42
Du musst für jeden Node eine eigene Instanz von TDataClass erzeugen und die auch in der DataLst speichern:
Delphi-Quellcode:
  Data := TDataClass.Create;
  DataLst.Add(Data);
  Data.Zeitraum := '01/2019';
  vnHead:= AddVSTStructureHeadClass(vstSP, nil, Data);

  Data := TDataClass.Create;
  DataLst.Add(Data);
  Data.Detail.Caption:='Zeile1:';
  Data.Detail.Wert1 := 'Det1 - Wert1';
  Data.Detail.Wert2 := 'Det1 - Wert2';
  Data.Detail.Wert3 := 'Det1 - Wert3';
  AddVSTStructureDetailClass(vstSP, vnHead, Data.Detail);

  Data := TDataClass.Create;
  DataLst.Add(Data);
  Data.Detail.Caption:='Zeile2:';
  Data.Detail.Wert1 := 'Det2 - Wert1';
  Data.Detail.Wert2 := 'Det2 - Wert2';
  Data.Detail.Wert3 := 'Det2 - Wert3';
  AddVSTStructureDetailClass(vstSP, vnHead, Data.Detail);
  Mit Zitat antworten Zitat
lowmax_5

Registriert seit: 9. Mai 2003
Ort: Münster, NRW
258 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: TVirtualStringTree mit TObjectList

  Alt 1. Mär 2019, 10:53
Argh , dass war es!
Kann im Nachgang auch nicht anders funktionieren...

Vielen Dank!!!
  Mit Zitat antworten Zitat
bcvs

Registriert seit: 16. Jun 2011
703 Beiträge
 
Delphi 12 Athens
 
#8

AW: TVirtualStringTree mit TObjectList

  Alt 1. Mär 2019, 10:59
Was mir noch aufgefallen ist: Das FreeNode des vst brauchst du nicht. Deine Data-Objekte werden ja von der DataLst verwaltet und freigegeben. Da ist es nicht gut, wenn der vst diese Objekte auf nil setzt.
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: TVirtualStringTree mit TObjectList

  Alt 1. Mär 2019, 12:11
Was mir noch aufgefallen ist: Das FreeNode des vst brauchst du nicht. Deine Data-Objekte werden ja von der DataLst verwaltet und freigegeben. Da ist es nicht gut, wenn der vst diese Objekte auf nil setzt.
Auf nil setzen ist nicht schlimm. Er gibt es ja nicht frei. Schlimmer wäre es, wenn er es bereits freigeben würde. Dann gäbe es eine AV.

Anders wäre das wenn er Interfaces nutzen würde. Dann muss er sie auch dort auf nil setzen, da sonst der Referenzzähler nicht dekrementiert wird.
  Mit Zitat antworten Zitat
bcvs

Registriert seit: 16. Jun 2011
703 Beiträge
 
Delphi 12 Athens
 
#10

AW: TVirtualStringTree mit TObjectList

  Alt 1. Mär 2019, 12:19
Auf nil setzen ist nicht schlimm. Er gibt es ja nicht frei. Schlimmer wäre es, wenn er es bereits freigeben würde. Dann gäbe es eine AV.
Und was ist, wenn die TOjectList später ihre Items freigeben will? Dann sind die nil und es gibt Speicherlecks.

Außerdem könnte es ja sein, dass man die Items außerhalb des VST noch braucht.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:23 Uhr.
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