VirtualTreeview

Rund um die LCL und andere Komponenten
Antworten
TT73GP7
Beiträge: 238
Registriert: Di 29. Mär 2016, 20:45

VirtualTreeview

Beitrag von TT73GP7 »

Hallo zusammen,

ich weiß gar nicht ob das VirtualTreeview überhaupt für meine zwecke das richtige ist.

ich suche ein grid welches zwei spalten hat.
erste spalte ein kleines Icon und zweite eine Beschreibung.

die Einträge müssen aufklappbar sein für weitere Eigenschaften.
nun ich denke damit bin ich ganz gut beraten. Mein Problem ist halt das ich so null Erfahrungen mit dem ding habe

wie ich die Spalten hinzufügen kann weiß ich
aber wie bekomme ich denn überhaupt Einträge darein?

aus dem wiki werde ich null schlau :(

http://wiki.lazarus.freepascal.org/Virt ... or_Lazarus

hat jemand für mich ein einfaches bespiel?

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: VirtualTreeview

Beitrag von fliegermichl »

Mit der Eigenschaft Tree.RootNodeCount kannst du die Anzahl der Einträge festlegen.

TT73GP7
Beiträge: 238
Registriert: Di 29. Mär 2016, 20:45

Re: VirtualTreeview

Beitrag von TT73GP7 »

hmm

ja aber was ist wenn ich nun drei einträge haben will

wie

test1
test2
test3

gut wenn ich den tree.RootNodeCount := 3 hoch setze habe ich aber immer noch nicht die drei Einträge drin

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: VirtualTreeview

Beitrag von fliegermichl »

Doch hast du,

Im Fall von dem VirtualStringTree musst du die Events onInitNode und onGetText implementieren.

In dem Package virtualtree_lcl gibt es jede Menge Demos die das zeigen.

TT73GP7
Beiträge: 238
Registriert: Di 29. Mär 2016, 20:45

Re: VirtualTreeview

Beitrag von TT73GP7 »

wow ist das umständlich

kann ich ein Note für den Text nicht direkt ansprechen?
und vorallen klappt das mit dem text überhaupt nicht so wie ich mir das vorstelle


Code: Alles auswählen

unit Main;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes,
  SysUtils,
  db,
  FileUtil,
  Forms,
  Controls,
  Graphics,
  Dialogs,
  StdCtrls,
  DBGrids,
  ZConnection,
  ZDataset,
  VirtualDBGrid,
  VirtualTrees;
 
type
 
  { TfrmMain }
 
  TfrmMain = class(TForm)
    Button1: TButton;
    btnAdd: TButton;
    dsUebersicht: TDataSource;
    ProjektBaum: TVirtualStringTree;
    zVerbindung: TZConnection;
    zUebersicht: TZQuery;
    procedure btnAddClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure ProjektBaumGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
    procedure ProjektBaumInitNode(Sender: TBaseVirtualTree; ParentNode,
      Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
  private
    nCount : Integer;
  public
  end;
 
var
  frmMain: TfrmMain;
 
implementation
 
{$R *.lfm}
 
{ TfrmMain }
 
procedure TfrmMain.btnAddClick(Sender: TObject);
begin
  ProjektBaum.RootNodeCount := ProjektBaum.RootNodeCount + 1;
end;
 
procedure TfrmMain.FormShow(Sender: TObject);
begin
  dsUebersicht.DataSet.First;
 
  while not dsUebersicht.DataSet.EOF do begin
    ProjektBaum.RootNodeCount := dsUebersicht.DataSet.FieldByName('ID').AsInteger;
    dsUebersicht.DataSet.next;
  end;
end;
 
 
 
procedure TfrmMain.ProjektBaumGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: String);
begin
   if (Column = 1) then begin
     CellText := dsUebersicht.DataSet.FieldByName('Projektname').AsString;
   end;
end;
 
procedure TfrmMain.ProjektBaumInitNode(Sender: TBaseVirtualTree; ParentNode,
  Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
begin
end;
 
end.
 

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: VirtualTreeview

Beitrag von fliegermichl »

Der VirtualTreeview selbst hat keine Texte. Du musst einen Record definieren, der die Daten beinhaltet die du für jede Node zum darstellen brauchst.
Das mit dem RootnodeCount ist ja nicht dafür gedacht um den Zeilenweise zu erhöhen sondern wenn man soviele Nodes auf einmal erstellen will.

Da du die Daten aus einer Datenbank holst, reicht es aus in dem Record die ID zu speichern oder den Namen gleich mit.

Code: Alles auswählen

 
type
 PMyRec = ^TMyRec;
 TMyRec = record
  id : integer;
  Projektname : string;
 end;
 
procedure TfrmMain.FormShow(Sender: TObject);
var myRec : PMyRec;
begin
  ProjektBaum.NodeDataSize := sizeOf(PMyRec);
  dsUebersicht.DataSet.First;
 
  while not dsUebersicht.DataSet.EOF do begin
    new(myRec);
    myRec^.id := dsUebersicht.DataSet.FieldByName('ID').AsInteger;
    myRec^.Projektname := dsUebersicht.DataSet.FieldByName('Projektname').AsString;
    ProjektBaum.AddChild(nil, myrec);
    dsUebersicht.DataSet.next;
  end;
end;
 
 


In ProjektBaumGetText schreibst du dann.

Code: Alles auswählen

 
procedure TfrmMain.ProjektBaumGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: String);
var myRec : PMyRec;
begin
  myRec := ProjektBaum.getNodeData(Node);
  case Column of
   -1, 0 : CellText := IntToStr(myRec^.Id);
       1 : CellText := myRec^.Projektname;
  end;
end;
 


Das scheint tatsächlich anfangs etwas umständlich zu sein aber dafür ist das extrem flexibel weil der Virtualtreeview keinerlei Annahmen über den Inhalt der darzustellenden Daten macht sondern alles über Events abfragt.

Ich habe für mich übrigens den VirtualTreeview etwas umgebaut weil ich immer die Instanz einer Klasse in die Trees hänge.
Dadurch spare ich mir das abholen der Daten mit Tree.GetNodeData sondern greife direkt auf Node.Data als Zeiger auf eine Klasseninstanz zu.

TT73GP7
Beiträge: 238
Registriert: Di 29. Mär 2016, 20:45

Re: VirtualTreeview

Beitrag von TT73GP7 »

hey Fliegermichl,

ahhhh es werde licht.
Nun stellt sich aber komplett eine andere Frage

ich glaube für mein vorhaben ist das die komplettfalsche Komponente. Ich Suche ja eher was die Eigenschaften eines DB Grid hat
aber es soll halt diesen Alten muss nicht haben.

Ergo ich hätte gerne Mehrzeiligkeit in einer Zelle und es sollen Icons dargestellt werden können

gut Icons bekomme ich auch in ein DB Grid
sieht aber alles noch so alt und muffig aus :(

Zur zeit erzeuge ich zur Laufzeit die Ganzen Labels und Icons
das ist nur leider sehr langsam :(

Daher bin ich auf der suche nach einen schöneren neuen DB Grid

hast du da Ideen?

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: VirtualTreeview

Beitrag von Socke »

TT73GP7 hat geschrieben:ich glaube für mein vorhaben ist das die komplettfalsche Komponente. Ich Suche ja eher was die Eigenschaften eines DB Grid hat
aber es soll halt diesen Alten muss nicht haben.

Um welchen "Alten muss" geht es denn? Das Aussehen des Headers stelle ich auch regelmäßig auf "tsNative" um.

Ansonsten kannst du in jedem Grid (TDrawGrid, TStringGrid, TDBGrid) die Zellen selbst zeichnen (siehe z.B. auch https://stackoverflow.com/questions/267 ... ll-drawing). Wenn du sämtliche Daten in eigenen Datenstrukturen ablegst und nur wenig Text hast, nimmst du TDrawGrid und zeichnest alles selbst.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: VirtualTreeview

Beitrag von wp_xyz »

TT73GP7 hat geschrieben:ich glaube für mein vorhaben ist das die komplettfalsche Komponente. Ich Suche ja eher was die Eigenschaften eines DB Grid hat

Wieso denn DBGrid? Im ganzen Beitrag war bisher nicht die Rede, dass es hier um Datenbanken geht. Ohne Datenbank-Hintergrund nimm lieber TStringGrid, oder TValueListEditor (= TStringGrid mit nur 2 Spalten), oder TListView im Report-Style. Letzteres hat Icon-Support eingebaut.

Hier ist allerdings nichts aufklappbar.

[EDIT] Ich sehe geraden im Beispielcode weiter oben, dass du tatsächlich mit Datenbanken arbeitest. Leider kann man hier seine eigenen Beiträge nicht löschen...

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: VirtualTreeview

Beitrag von fliegermichl »

Der VirtualTreeview ist schon sehr gut geeignet. Über die TreeOptions kannst Du die Gridfunktionen aktivieren.
Damit die Spaltennamen sichtbar werden, muss Header->Options->hoVisible auf True gestellt werden.

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: VirtualTreeview

Beitrag von hubblec4 »

Ich würde auch nur noch auf ein VST zurückgreifen, es arbeitet sich damit wesentlich leichter.

OK, auch ich habe anfangs da so meine Schwierigkeiten gehabt, es ist schon eine recht "große" Komponente.
Jedoch wenn man sich dann etwas auskennt merkt man das soooo viele Vorteile vorhanden sind.

Das klassiche Tutorial zu dem VST ist für Einsteiger sicher ein guter Anfang.
ABER: So würde ich nicht mehr mit VST arbeiten. Im Tutorial wird für den NodeText immer erst ein Record(man kann auch ne Klasse/Instanz) angelegt.
In diesem dann Text abgelegt und im "onGetText" Event, erst die Node-Daten holen(zugriff auf das Record) und dann wird der Text zugewiesen.
Hierbei muss noch eine "onNodeInit" procedure bestückt werden....naja alles viel Vorbereitungsarbeit.


Ich mache das jetzt immer so, das zu einem VST eine Datenklasse gehört (man soll ja sowieso Daten und GUI-Komponenten voneinander trennen).

Also grobes Beispiel. Alle deine Datenbankeinträge (was ja auch schon wie so eine Art eigene Klasse angesehen werden kann) kannst du direkt im onGetText-Event den Node-Text zuweisen. Dabei würde aber immer wieder auf die Datenbank zugeriffen da die Nodetexte dynamisch dargestellt werden.
Du könntest als Datenklasse ein TStringlist nutzen. Alle Daten(Texte) die du anzeigen willst kommen dort "einmal" rein und dann kannst du die Texte leicht darstellen lassen.


Code: Alles auswählen

 
var SL:TStringList;
 
procedure TfrmMain.ProjektBaumGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: String);
begin
  CellText := SL[Node^.index]
end;


Wenn du mehrere Zellen mit unterschiedlichem Text hast brauchst du etwas anderes als eine StringList.
Ich habe in meinen Projekten wiegesagt immer eine Daten Klasse.

Code: Alles auswählen

 
type MeineDatenklasse: TMyData;
var ObjectList: TObjectList;
 
procedure TfrmMain.ProjektBaumGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: String);
begin
  case Column of
     0 : CellText := TMyData(ObjectList.items[Node^.index]).Text_1;
     1 : CellText := TMyData(ObjectList.items[Node^.index]).Text_2;
  end;
 
 
// oder kürzer
  with TMyData(ObjectList.items[Node^.index]) do
  case Column of
     0 : CellText := Text_1;
     1 : CellText := Text_2;
  end;
 
end;


EDIT:
Für diese art der Darstellung von Texten (und auch Bilder wenn man mag) spart einiges an Vorbereitungen und was am aller wichtigsten ist, du arbeitest Komponenten unabhängiger.
Du könntest das VST gegen etwas anderes ersetzen und musst dann noch noch in GUI die Ausgabe/Ansicht anpassen.

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: VirtualTreeview

Beitrag von hubblec4 »

fliegermichl hat geschrieben:...
Ich habe für mich übrigens den VirtualTreeview etwas umgebaut weil ich immer die Instanz einer Klasse in die Trees hänge.
Dadurch spare ich mir das abholen der Daten mit Tree.GetNodeData sondern greife direkt auf Node.Data als Zeiger auf eine Klasseninstanz zu.


Genau so ähnlich hatte ich das auch mal versucht, da mir das "Daten holen" und Record anlegen umständlich vorkam.

Aber eben auch deine Methode hinterlegt "Zugangs-Punkte" in einem Node ab.
Also wenn du in deinem Programm was machts, was Nodes hinzufügen lässt, dann musst du in jedem neuen Node die Daten-Klasse zuweisen.
Wenn du also das VST mal austauschen musst, müsstest du dir dann wieder in der GUI Gedanken machen alles ordentlich anzeigen zu lassen,
oder wie machst du das?

Antworten