AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Datenbank in VirtualTreeView anzeigen und auswerten
Thema durchsuchen
Ansicht
Themen-Optionen

Datenbank in VirtualTreeView anzeigen und auswerten

Ein Thema von Jens Hartmann · begonnen am 3. Mär 2009 · letzter Beitrag vom 20. Mär 2009
Antwort Antwort
Seite 6 von 9   « Erste     456 78     Letzte »    
generic

Registriert seit: 24. Mär 2004
Ort: bei Hannover
2.416 Beiträge
 
Delphi XE5 Professional
 
#51

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 8. Mär 2009, 13:04
Zitat von Jens Hartmann:
Delphi-Quellcode:
var
  Daten : TOMB256PLUS;
begin
Daten := TOMB256PLUS.Create;
Objekt erzeugen

Zitat von Jens Hartmann:
Daten := TOMB256PLUS(VST.GetNodeData(Node)^);
nun den Zeiger wieder überschreiben und die Referenz verlieren.
Somit ist die gerade zuvor erzeugte Instanz von die nicht mehr zu benutzen.
Kurz: Die .Create Zeile ist zuviel und das im ganzen Code.

Es reicht ein mal das Objekt pro Datensatz zu erstellen.
Das machst du ja bereits bei der Init Routine.

Delphi-Quellcode:
  
procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; ParentNode,
  Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
  Daten : TOMB256PLUS;

[...]
Daten := TOMB256PLUS.Create;
  VST.NodeHeight[Node] := 35;
  Include(InitialStates, ivsMultiline);
  Initialize(Daten);
Was macht deine "Initialize" Daten Funktion?
Wann weist du den Objektzeiger dem VST-Data Zeiger zu?
Jede Zeile hat ein pVirtualNode Record, an diesem hängt der Datenzeiger. Diesen scheinst du nicht zu setzen. Daher die Schutzverletzung.




Daher geht dein GetText usw. nicht, weil es keine Referenz auf deine TOMB256PLUS Objekte findet.
Coding BOTT - Video Tutorials rund um das Programmieren - https://www.youtube.com/@codingbott
  Mit Zitat antworten Zitat
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#52

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 8. Mär 2009, 14:52
Ich habe das ganze jetzt mal umgebaut, und dazu das Tutorial aus dem DelphiTreff zur Hilfe genommen.

Allerdings, klappt das alles nicht so, wie ich mir das vorstelle.

Delphi-Quellcode:
{VST Initialisieren mit den Daten aus der Datenbank}
procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; ParentNode,
  Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
  Daten : TOMB256PLUS;

begin
  VST.NodeDataSize := SizeOf(TOMB256PLUS);
  VST.NodeHeight[Node] := 35;
  while not QryMB256PLUS.Eof do
    begin
        Daten := TOMB256PLUS.Create;
        try
        Daten.ID := QRYMB256PLUS.FieldByName('ID').AsInteger;
        Daten.LfdNr := QRYMB256PLUS.FieldByName('LfdNr').AsInteger;
        Daten.Datum := QRYMB256PLUS.FieldByName('Datum').AsString;
        Daten.Uhrzeit := QRYMB256PLUS.FieldByName('Uhrzeit').AsString;
        Daten.Ereignis := QRYMB256PLUS.FieldByName('Ereignis').AsString;
        Daten.Teilnehmer := QRYMB256PLUS.FieldByName('Teilnehmer').AsString;
        Daten.Bereich := QRYMB256PLUS.FieldByName('Bereich').AsString;
        VST.AddChild(nil,Daten);
        except
        Daten.Free;
      end;
    end;
end;

Allerdings, habe ich das da auch nicht so ganz verstanden, In einem Video hier in der DP wird das VST einmal mit einem Record und einmal mit einem Object gefüllt. Im Tutorial ist dem Object irgendwie einRecord zugewiesen.
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
generic

Registriert seit: 24. Mär 2004
Ort: bei Hannover
2.416 Beiträge
 
Delphi XE5 Professional
 
#53

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 8. Mär 2009, 17:16
VST.AddChild(nil,Daten); ist an der Stelle auch falsch.

mit addChild fügst du einen neuen Knoten hinzu (Würde auch generell gehen, wäre dein Projekt etwas anders aufgebaut).
Da du das NodeCount setzt, sind die Knoten schon im Baum. Du brauchst also nur noch den Zeiger zeigen lassen ;-)

Also hat du nun 2 Möglichkeiten.

a) du nimmst den code aus dem letzten post und löscht aus deinem projekt die andere initialisierung

oder

b) du entfernst die schleife aus der init routine und lässt bei dem node den datenzeiger auf dein objekt zeigen.
Coding BOTT - Video Tutorials rund um das Programmieren - https://www.youtube.com/@codingbott
  Mit Zitat antworten Zitat
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#54

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 9. Mär 2009, 17:51
Also irgendwie bin ich scheinba zu doof da zu.

Diese ganzen Möglichkeiten von Records, Objecten oder Objecten mit Records, hat mich total durcheinander gebracht.
Ich poste Euch jetzt nochmal, meinen zur Zeit aktiven geamten Code der das VST angeht. Vieleicht, kann mir da dann ja mal jemand dran erklären, wo mein Fehler ist, und vorallem warum.

Delphi-Quellcode:
//Wird so in der Funktion aufgerufen, die meine Daten verwaltet.
  
  QryMB256PLUS.Close;
  QryMB256PLUS.SQL.Text := 'SELECT * FROM MB256PLUS';//'SELECT * FROM MB256PLUS';
  QryMB256PLUS.Open;

  Form1.VSTfüllen; //Eigene Procedure
end;

procedure TForm1.VSTfüllen;
var
  Daten : TOMB256PLUS;
begin
if not QRYMB256PLUS.Active then
  QRYMB256PLUS.Open;
  QRYMB256PLUS.filtered := false;
  QRYMB256PLUS.filter := '';
  VST.BeginUpdate;
  VST.Clear;
  VST.NodeDataSize := Sizeof(TOMB256PLUS);
  Daten := TOMB256PLUS.Create;
  QRYMB256PLUS.First;
  VST.RootNodeCount := QRYMB256PLUS.RecordCount;
  VST.SortTree(0,sdAscending,true);
  VST.EndUpdate;
end;

{Größe vom Objekt dem VST zuweisen}
procedure TForm1.VSTGetNodeDataSize(Sender: TBaseVirtualTree;
  var NodeDataSize: Integer);
begin
  VST.NodeDataSize := SizeOf(TOMB256PLUS);
end;

{Werte dem VST zuweisen}
procedure TForm1.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
  Daten : TOMB256PLUS;
begin
//Daten := TOMB256PLUS.Create;
Daten := TOMB256PLUS(VST.GetNodeData(Node)^);
  case Column of
  0: CellText:= IntToStr(Daten.ID);
  1: CellText:= IntToStr(Daten.LfdNr);
  2: CellText:= Daten.Datum;
  3: CellText:= Daten.Uhrzeit;
  4: CellText:= Daten.Ereignis;
  5: CellText:= Daten.Teilnehmer;
  6: CellText:= Daten.Bereich;
  end;
end;



procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; ParentNode,
  Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
  Daten : TOMB256PLUS;
begin
        Daten.ID := QRYMB256PLUS.FieldByName('ID').AsInteger;
        Daten.LfdNr := QRYMB256PLUS.FieldByName('LfdNr').AsInteger;
        Daten.Datum := QRYMB256PLUS.FieldByName('Datum').AsString;
        Daten.Uhrzeit := QRYMB256PLUS.FieldByName('Uhrzeit').AsString;
        Daten.Ereignis := QRYMB256PLUS.FieldByName('Ereignis').AsString;
        Daten.Teilnehmer := QRYMB256PLUS.FieldByName('Teilnehmer').AsString;
        Daten.Bereich := QRYMB256PLUS.FieldByName('Bereich').AsString;
end;

procedure TForm1.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
  Daten : TOMB256PLUS;
begin
  Daten := TOMB256PLUS(VST.GetNodeData(Node)^);
  Daten.Free;
end;
Das müssten alle Funktionen sein.
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
generic

Registriert seit: 24. Mär 2004
Ort: bei Hannover
2.416 Beiträge
 
Delphi XE5 Professional
 
#55

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 9. Mär 2009, 21:02
Delphi-Quellcode:
procedure TForm1.VSTfüllen;
var
  Daten : TOMB256PLUS;
begin
if not QRYMB256PLUS.Active then
  QRYMB256PLUS.Open;
  QRYMB256PLUS.filtered := false;
  QRYMB256PLUS.filter := '';
  VST.BeginUpdate;
  VST.Clear;
  VST.NodeDataSize := Sizeof(TOMB256PLUS);
  Daten := TOMB256PLUS.Create;
  QRYMB256PLUS.First;
  VST.RootNodeCount := QRYMB256PLUS.RecordCount;
  VST.SortTree(0,sdAscending,true);
  VST.EndUpdate;
end;
Wofür brauchst du da ein neues Daten Objekt? Was passiert damit?

Delphi-Quellcode:
procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; ParentNode,
  Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
  Daten : TOMB256PLUS;
begin
        Daten.ID := QRYMB256PLUS.FieldByName('ID').AsInteger;
        Daten.LfdNr := QRYMB256PLUS.FieldByName('LfdNr').AsInteger;
        Daten.Datum := QRYMB256PLUS.FieldByName('Datum').AsString;
        Daten.Uhrzeit := QRYMB256PLUS.FieldByName('Uhrzeit').AsString;
        Daten.Ereignis := QRYMB256PLUS.FieldByName('Ereignis').AsString;
        Daten.Teilnehmer := QRYMB256PLUS.FieldByName('Teilnehmer').AsString;
        Daten.Bereich := QRYMB256PLUS.FieldByName('Bereich').AsString;
end;
So jetzt weisst du hier einen nicht initialisierten Objekt dazu zu.
Müsste sogar in der IDE eine Warnung stehen.

Wie wäre es HIER das Datenobjekt zu erzeugen (.Create) und anschließend den Zeiger zu dem Objekt an den Node-Datenzeiger hängen bzw. zuweisen.
Wobei ich persönlich das arbeiten über InitNode vermeide, da etwas komplizierter und die Knotenanzahl fest stehen muss.
InitNode ist aber performanter als eine iteratives vorgehen.

Der Rest deines Codes sieht ganz gut aus. Aber ich habe den Eindruck das du noch nicht viel mit Objekten und Zeiger gearbeitet hast.
Coding BOTT - Video Tutorials rund um das Programmieren - https://www.youtube.com/@codingbott
  Mit Zitat antworten Zitat
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#56

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 9. Mär 2009, 22:37
Genau, das ist mein Problem, und das verstehe ich auch irgendwie nicht so recht, und um ehrlich zu sein, habe ich bislang noch gar nicht mit Objekten gearbeitet. Das ist jetzt durch das VST entstanden.

In einem Übungsbeispiel, wurde damit gearbeitet. In einem anderen Übungsbeispiel mit Records.

Und durch diese Geschichte bin ich auch total verwirrt mittlerweile. Ich habe mein Programm jetzt wieder umgebaut auf einen Record, und damit Funktioniert es so wie ich es mir vorstelle.

Hier der Quellcode.

Die Frage ist nur, ob es der Richtige und sichere Weg ist. Ich lese Daten von einer COM Schnittstelle, die in einer undefinierbaren Menge auftreten können.

Das VST nutze ich zur Anzeige dieser Datensätze, die unter diversen Umständen im Sekunden Takt auftreten könne.

Delphi-Quellcode:

type
  PVSTRec = ^VSTRec;
  VSTRec = packed record
    ID, LfdNr : integer;
    Datum, Uhrzeit, Ereignis, Teilnehmer, Bereich : WideString;
    SysDatum : String;
  end;


procedure TForm1.VSTFüllen; //Das VSTFüllen wird bei jedem neuen Datensatz aufgerufen,
begin //dadurch realisiere ich, das die Anzeige immer aktuell ist.
if not QryMB256PLUS.Active then
  QryMB256PLUS.Open;
  QryMB256PLUS.filtered := false;
  QryMB256PLUS.filter := '';
  VST.BeginUpdate;
  VST.Clear;
  VST.NodeDataSize := SizeOf(VSTRec);
  QryMB256PLUS.First;
  VST.RootNodeCount := QryMB256PLUS.RecordCount;
  VST.SortTree(0,sdAscending,true);
  VST.EndUpdate;
end;

procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree;
  ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
    Daten : PVSTRec;
begin
  Daten := Sender.GetNodeData(Node);
  VST.NodeHeight[Node] := 35;
  Include(InitialStates, ivsMultiline);
  Initialize(Daten^);
  Daten.ID := QryMB256PLUS.FieldByName('ID').AsInteger;
  Daten.LfdNr := QryMB256PLUS.FieldByName('LfdNr').AsInteger;
  Daten.Datum := QryMB256PLUS.FieldByName('Datum').AsString;
  Daten.Uhrzeit := QryMB256PLUS.FieldByName('Uhrzeit').AsString;
  Daten.Ereignis := QryMB256PLUS.FieldByName('Ereignis').AsString;
  Daten.Teilnehmer := QryMB256PLUS.FieldByName('Teilnehmer').AsString;
  Daten.Bereich := QryMB256PLUS.FieldByName('Bereich').AsString;
  if not QryMB256PLUS.eof then
    QryMB256PLUS.Next;
end;

procedure TForm1.VSTPaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  Daten : PVSTRec;
begin

  Daten := Sender.GetNodeData(Node);


  if Sender.Selected[Node] then
    Exit;
    
  Daten := (VST.GetNodeData(Node));

  if Pos('Extern',Daten.Ereignis) > 0 then
    TargetCanvas.Font.Color := clYellow;


end;

procedure TForm1.VSTAfterItemErase(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; ItemRect: TRect);
var
  Daten : PVSTRec;
begin

  Daten := Sender.GetNodeData(Node);


  if Sender.Selected[Node] then
    Exit;
    
  Daten := (VST.GetNodeData(Node));

  if Pos('Extern',Daten.Ereignis) > 0 then
    TargetCanvas.Brush.Color := clblue;

  if Pos('Unscharf',Daten.Ereignis) > 0 then
    TargetCanvas.Brush.Color := clLime;

  if Pos('Störung',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clYellow;
    end;

  if Pos('Alarm',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Hauptalarm',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Überfall',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Einbruch',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Sabotage',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Voralarm',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;


  TargetCanvas.FillRect (ItemRect);

end;

procedure TForm1.VSTFreeNode(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
var
  Daten : PVSTRec;
begin
  Daten := Sender.GetNodeData(Node);
  if Assigned(Daten) then
    Finalize(Daten^);
end;

procedure TForm1.VSTGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: WideString);
var
    Daten : PVSTRec;
begin
Daten := Sender.GetNodeData(Node);
  case Column of
  0: CellText:= IntToStr(Daten.ID);
  1: CellText:= IntToStr(Daten.LfdNr);
  2: CellText:= Daten.Datum;
  3: CellText:= Daten.Uhrzeit;
  4: CellText:= Daten.Ereignis;
  5: CellText:= Daten.Teilnehmer;
  6: CellText:= Daten.Bereich;
  end;
end;

procedure TForm1.VSTHeaderClick(Sender: TVTHeader;
  Column: TColumnIndex; Button: TMouseButton; Shift: TShiftState; X,
  Y: Integer);
begin
if Button = mbLeft then
  with Sender do
    begin
    if SortColumn <> Column then
       SortColumn := Column;
    if SortDirection = sdAscending then
       SortDirection := sdDescending
    else SortDirection := sdAscending;
    VST.SortTree(Column,SortDirection,true);
    end;
end;
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#57

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 10. Mär 2009, 16:39
So, war zwar ne schwere Geburt, aber ich habe es doch noch hinbekommen, meine VST Anbindung ohne InitFunktion und mit Object zu gestalten.

Ich hoffe, das jemand diesen Beitrag ließt, und eventuell mal sagen kann, ob ich das jetzt so richtig gemacht habe oder, ob ich noch was ändern muss oder sollte.

Die Funktion ist komplett da und in Ordnung.

Ich weiß nur nicht so genau, ob das mit den Einträgen einfügen und so alles so OK ist, ohne das ich nachher irgendwelche Performance Problem bekomme.

Hier mal meine jetzige und hoffendlich fertige Lösung..

Delphi-Quellcode:

//Mein Object
type
  TOMB256PLUS = class
    private
    ID : integer;
    LfdNr : integer;
    Datum : String;
    Uhrzeit : String;
    Ereignis : String;
    Teilnehmer : String;
    Bereich : String;
    SysData : String;
  end;

//Eintrag in Form.Create
VST.NodeDataSize := SizeOf(TOMB256PLUS);
VSTFüllen;
VST.ScrollIntoView(VST.GetLast, true);

//Funktion VSTFüllen die durch FormCreate ausgelößt wird
procedure TForm1.VSTFüllen;
var
  Daten : TOMB256PLUS;
begin
if not QryMB256PLUS.Active then
  QryMB256PLUS.Open;
  QryMB256PLUS.filtered := false;
  QryMB256PLUS.filter := '';
  VST.BeginUpdate;
  VST.Clear;
  VST.NodeDataSize := SizeOf(TOMB256PLUS);

  while not QryMB256PLUS.EOF do
    begin
      Daten := TOMB256PLUS.Create;
      with Daten do
      begin
        Daten.ID := QryMB256PLUS.FieldByName('ID').AsInteger;
        Daten.LfdNr := QryMB256PLUS.FieldByName('LfdNr').AsInteger;
        Daten.Datum := QryMB256PLUS.FieldByName('Datum').AsString;
        Daten.Uhrzeit := QryMB256PLUS.FieldByName('Uhrzeit').AsString;
        Daten.Ereignis := QryMB256PLUS.FieldByName('Ereignis').AsString;
        Daten.Teilnehmer := QryMB256PLUS.FieldByName('Teilnehmer').AsString;
        Daten.Bereich := QryMB256PLUS.FieldByName('Bereich').AsString;
      end;
      VST.AddChild(nil,Daten);
      QryMB256PLUS.Next;
    end;
  VST.EndUpdate;
end;

//Einträge in VST einfügen, wenn neue Datensätze kommen.
{Datensatzverarbeitung}
procedure TForm1.TreeViewResult(ParserTreeView: TMyBaseParser);
var
  i: Integer;
  Temp1 : Integer;
  Temp2 : String;
  Temp3 : String;
  Temp4 : String;
  Temp5 : String;
  Temp6 : String;
  Daten : TOMB256PLUS;
begin
  Temp1 := ParserTreeView.Entries[0].LfdNr;
  Temp2 := ParserTreeView.Entries[0].Datum;
  Temp3 := ParserTreeView.Entries[0].Uhrzeit;
  Temp4 := ParserTreeView.Entries[0].Ereignis;
  Temp5 := ParserTreeView.Entries[0].Teilnehmer;
  Temp6 := ParserTreeView.Entries[0].Bereich;
  Application.ProcessMessages;

  QryMB256PLUS.Close;
  QryMB256PLUS.SQL.Text := 'INSERT INTO MB256PLUS'+
      '("LfdNr", "Datum", "Uhrzeit", "Ereignis", "Teilnehmer", "Bereich")'+
      'VALUES(:LfdNr,:Datum,:Uhrzeit,:Ereignis,:Teilnehmer,:Bereich)';

  QryMB256PLUS.ParamByName('LfdNr').AsInteger := Temp1;
  QryMB256PLUS.ParamByName('Datum').AsString := Temp2;
  QryMB256PLUS.ParamByName('Uhrzeit').AsString := Temp3;
  QryMB256PLUS.ParamByName('Ereignis').AsString := Temp4;
  QryMB256PLUS.ParamByName('Teilnehmer').AsString := Temp5;
  QryMB256PLUS.ParamByName('Bereich').AsString := Temp6;

  QryMB256PLUS.ExecSQL;
  ConMB256PLUS.Commit;

  QryMB256PLUS.Close;
  QryMB256PLUS.SQL.Text := 'SELECT * FROM MB256PLUS';//'SELECT * FROM MB256PLUS';
  QryMB256PLUS.Open;

  VST.BeginUpdate;
  Daten := TOMB256PLUS.Create;
  QryMB256PLUS.Last;
  with Daten do
  begin
    Daten.ID := QryMB256PLUS.FieldByName('ID').AsInteger;
    Daten.LfdNr := QryMB256PLUS.FieldByName('LfdNr').AsInteger;
    Daten.Datum := QryMB256PLUS.FieldByName('Datum').AsString;
    Daten.Uhrzeit := QryMB256PLUS.FieldByName('Uhrzeit').AsString;
    Daten.Ereignis := QryMB256PLUS.FieldByName('Ereignis').AsString;
    Daten.Teilnehmer := QryMB256PLUS.FieldByName('Teilnehmer').AsString;
    Daten.Bereich := QryMB256PLUS.FieldByName('Bereich').AsString;
  end;
  VST.AddChild(nil, Daten);

  VST.ScrollIntoView(VST.GetLast, true);
  VST.EndUpdate;
  DataMB256plus := '';
end;

//Celltext Zuweisung
procedure TForm1.VSTGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: WideString);
var
    Daten : TOMB256PLUS;
begin
  Daten := TOMB256PLUS(VST.GetNodeData(Node)^);
  case Column of
  0: CellText:= IntToStr(Daten.ID);
  1: CellText:= IntToStr(Daten.LfdNr);
  2: CellText:= Daten.Datum;
  3: CellText:= Daten.Uhrzeit;
  4: CellText:= Daten.Ereignis;
  5: CellText:= Daten.Teilnehmer;
  6: CellText:= Daten.Bereich;
  end;
end;

//Objectdaten freigeben
procedure TForm1.VSTFreeNode(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
var
  Daten : TOMB256PLUS;
begin
  Daten := TOMB256PLUS(VST.GetNodeData(Node)^);
  Daten.Free;
end;

//Zeilen, je nach Ereignis einfärben
procedure TForm1.VSTAfterItemErase(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; ItemRect: TRect);
var
  Daten : TOMB256PLUS;
begin

  Daten := TOMB256PLUS(VST.GetNodeData(Node)^);

  if Sender.Selected[Node] then
    Exit;

  if Pos('Extern',Daten.Ereignis) > 0 then
    TargetCanvas.Brush.Color := clblue;

  if Pos('Unscharf',Daten.Ereignis) > 0 then
    TargetCanvas.Brush.Color := clLime;

  if Pos('Störung',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clYellow;
    end;

  if Pos('Alarm',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Hauptalarm',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Überfall',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Einbruch',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Sabotage',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  if Pos('Voralarm',Daten.Ereignis) > 0 then
    begin
      if Pos('EIN', Daten.Ereignis) > 0 then
        TargetCanvas.Brush.Color := clRed;
    end;

  TargetCanvas.FillRect (ItemRect);


end;

//Textfarbe bei blauen Zellen auf gelb setzen
procedure TForm1.VSTPaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  Daten : TOMB256PLUS;
begin
  Daten := TOMB256PLUS(VST.GetNodeData(Node)^);

  if Sender.Selected[Node] then
    Exit;

  if Pos('Extern',Daten.Ereignis) > 0 then
    TargetCanvas.Font.Color := clYellow;
end;
Ich bedanke mich schon mal, und hoffe auf Eure antworten.

Gruß Jens
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
generic

Registriert seit: 24. Mär 2004
Ort: bei Hannover
2.416 Beiträge
 
Delphi XE5 Professional
 
#58

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 10. Mär 2009, 22:00
Sieht ganz gut aus, aber einen müssen wir abziehen, hätten die bei Rosental gesagt.

Du hast ein
VST.NodeDataSize := SizeOf(TOMB256PLUS); doppelt.

Eigentlich reicht der eine im CreateForm.

Wenn du einen Datensatz hinzufügst, würde ich die Daten direkt in das VST Objekt schreiben und dem VST hinzufügen.
Erst in die DB schreiben und dann wieder alle DS laden, um dann zum letzten zu springen um diesen dann in das Objekt zu kopieren
erscheint mir etwas umständlich.


Kleine Anmerkung noch zu der Recordlösung.
Dort nutzt du die Datentype String und Widestring. Dieses sind Zeigertypen.

Records sind einfach ausdrückt zusammenhängende Speicherblöcke optimal ohne Zeiger drin.
So kann dieser Speicherblock direkt z.B. von/auf Festplatte geschrieben/geladen werden ohne die Daten im Speicher zu suchen zu müssen.

Der VST z.B. nutzt die Records um Geschwindigkeit gut zu machen.
Bei 100 Datensätzen wird nur 1 mal Speicher belegt. Dadurch geht das sehr schnell.
Nutzt du nun Huge-/Wide-Strings dann wird im Record nur ein Zeiger zu dem String abgelegt.

Der kann zwar ganz normal genutzt werden, wird aber vom VST nicht mehr freigegeben und du erhälst Speicherlöcher.
Das kannst du mit dem FastMM kontrollieren. Ein Beispiel befindet sich auch im DP Stammtischvideo #2.

Es gibt 2,5 Möglichkeiten da drum rum zu kommen.
1) Shortstrings verwenden z.B. String[255] wobei die Stringlänge =<255 sein muss
2) du gibts den Huge-/Wide-String frei bei dem onFreeNode Ereignis
2,5) du schaltest die Hugestrings im Compiler aus

Die Objektmethode ist dort anders.
Im onFreeNode wird das komplett Objekt freigegeben also ist das gut.
Nachteil bei 100 Datensätzen fordert der VST 100 mal Speicher für den Knoten im addNode an. Dauert dadurch etwas länger.
Coding BOTT - Video Tutorials rund um das Programmieren - https://www.youtube.com/@codingbott
  Mit Zitat antworten Zitat
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#59

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 10. Mär 2009, 22:42
Hallo generic,

Erstmal großes Dankeschön, für die gute Erklärung. Die VSTFüllen, habe ich abgewandelt.

Delphi-Quellcode:
procedure TForm1.VSTFüllen;
var
  Daten : TOMB256PLUS;
begin
if not QryMB256PLUS.Active then
  QryMB256PLUS.Open;
  QryMB256PLUS.filtered := false;
  QryMB256PLUS.filter := '';
  VST.BeginUpdate;
  VST.Clear;


  //VST.NodeDataSize := SizeOf(TOMB256PLUS);



  while not QryMB256PLUS.EOF do
    begin
      Daten := TOMB256PLUS.Create;
      with Daten do
      begin
        Daten.ID := QryMB256PLUS.FieldByName('ID').AsInteger;
        Daten.LfdNr := QryMB256PLUS.FieldByName('LfdNr').AsInteger;
        Daten.Datum := QryMB256PLUS.FieldByName('Datum').AsString;
        Daten.Uhrzeit := QryMB256PLUS.FieldByName('Uhrzeit').AsString;
        Daten.Ereignis := QryMB256PLUS.FieldByName('Ereignis').AsString;
        Daten.Teilnehmer := QryMB256PLUS.FieldByName('Teilnehmer').AsString;
        Daten.Bereich := QryMB256PLUS.FieldByName('Bereich').AsString;
      end;
      VST.AddChild(nil,Daten);
      QryMB256PLUS.Next;
    end;
  VST.EndUpdate;
end;
Allerdings, mit der anderen, denke ich muss das so bleiben. Den Grund dafür, sehe ich, da beim schreiben in die Datenbank, ein ID erzeugt wird. (Generator der Firebird als Zähler).

Delphi-Quellcode:
  //QryMB256PLUS.ParamByName('ID') wird durch die Datenbank erzeugt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
  QryMB256PLUS.ParamByName('LfdNr').AsInteger := Temp1;
  QryMB256PLUS.ParamByName('Datum').AsString := Temp2;
  QryMB256PLUS.ParamByName('Uhrzeit').AsString := Temp3;
  QryMB256PLUS.ParamByName('Ereignis').AsString := Temp4;
  QryMB256PLUS.ParamByName('Teilnehmer').AsString := Temp5;
  QryMB256PLUS.ParamByName('Bereich').AsString := Temp6;
Was für mich bedeuten tut, will ich die ID im VST sehen, muss ich diese ja aus der Datenbankabfragen, Oder?
Delphi-Quellcode:
  VST.BeginUpdate;
  Daten := TOMB256PLUS.Create;
  QryMB256PLUS.Last;
  with Daten do
  begin
    Daten.ID := QryMB256PLUS.FieldByName('ID').AsInteger;
    Daten.LfdNr := QryMB256PLUS.FieldByName('LfdNr').AsInteger;
    Daten.Datum := QryMB256PLUS.FieldByName('Datum').AsString;
    Daten.Uhrzeit := QryMB256PLUS.FieldByName('Uhrzeit').AsString;
    Daten.Ereignis := QryMB256PLUS.FieldByName('Ereignis').AsString;
    Daten.Teilnehmer := QryMB256PLUS.FieldByName('Teilnehmer').AsString;
    Daten.Bereich := QryMB256PLUS.FieldByName('Bereich').AsString;
  end;
  VST.AddChild(nil, Daten);
  VST.ScrollIntoView(VST.GetLast, true);
  VST.EndUpdate;
Da ich keine Zeitprobleme habe, und es kein Problem ist die Datenbank bei Programmstart zu laden, müsste die Variante mit den Objecten ja die bessere sein.

Gibt es den da irgendeine Beschränkung der Anzahl der Datensätz, wo das keinen Sinn mehr macht, oder anders gefragt. Sollte ich das VST auf irgendeine bestimmte Anzahl Datensätze Begrenzen und nur bei Abfrage durch den Kunden die anderen sichbar machen.

Ich denke da an so was...
Delphi-Quellcode:
  Count := QryMB256PLUS.RecordCount-10000;
  QryMB256PLUS.RecNo := Count;

  while not QryMB256PLUS.EOF do
  begin
      Daten := TOMB256PLUS.Create;
      with Daten do
      begin
        Daten.ID := QryMB256PLUS.FieldByName('ID').AsInteger;
        Daten.LfdNr := QryMB256PLUS.FieldByName('LfdNr').AsInteger;
        Daten.Datum := QryMB256PLUS.FieldByName('Datum').AsString;
        Daten.Uhrzeit := QryMB256PLUS.FieldByName('Uhrzeit').AsString;
        Daten.Ereignis := QryMB256PLUS.FieldByName('Ereignis').AsString;
        Daten.Teilnehmer := QryMB256PLUS.FieldByName('Teilnehmer').AsString;
        Daten.Bereich := QryMB256PLUS.FieldByName('Bereich').AsString;
      end;
      VST.AddChild(nil,Daten);
      QryMB256PLUS.Next;
    end;
  VST.EndUpdate;
end;
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#60

Re: Datenbank in VirtualTreeView anzeigen und auswerten

  Alt 15. Mär 2009, 09:18
Hallo nochmal zusammen,

habe das ganze jetzt ausgiebig geprüft, und habe leider festgestellt, das da noch irgendein zeitliches Problem bestehen muss.

Starte ich meine Verbindung um Daten von der COM Schnittstelle zu holen, geht das, möchte ich diese allerdings wieder trennen, kommen zwar keine weiteren Daten ins VST, aber mein Programm scheint an irgendeiner Stelle hängen zu bleiben. Oder was ich eher Vermute, weil wenn ich lange Daten hole, und mein Programm minimiere, und später wieder vergrößern will, dauert das unwahrscheinlich lange bis das VST neu gezeichnet ist oder es hgeht gar nicht.

Daher vermute ich, das ich mir irgendwo den Speicher zu mülle.

Mein Object gebe ich allerdings wieder frei.

Hier mal der Code..

Delphi-Quellcode:
{Datensatzverarbeitung}
procedure TForm1.TreeViewResult(ParserTreeView: TMyBaseParser);
var
  i: Integer;
  Temp1 : Integer;
  Temp2 : String;
  Temp3 : String;
  Temp4 : String;
  Temp5 : String;
  Temp6 : String;
  Daten : TOMB256PLUS;
begin
  Temp1 := ParserTreeView.Entries[0].LfdNr;
  Temp2 := ParserTreeView.Entries[0].Datum;
  Temp3 := ParserTreeView.Entries[0].Uhrzeit;
  Temp4 := ParserTreeView.Entries[0].Ereignis;
  Temp5 := ParserTreeView.Entries[0].Teilnehmer;
  Temp6 := ParserTreeView.Entries[0].Bereich;
  QryMB256PLUS.Close;
  QryMB256PLUS.SQL.Text := 'INSERT INTO MB256PLUS'+
      '("LfdNr", "Datum", "Uhrzeit", "Ereignis", "Teilnehmer", "Bereich")'+
      'VALUES(:LfdNr,:Datum,:Uhrzeit,:Ereignis,:Teilnehmer,:Bereich)';

  QryMB256PLUS.ParamByName('LfdNr').AsInteger := Temp1;
  QryMB256PLUS.ParamByName('Datum').AsString := Temp2;
  QryMB256PLUS.ParamByName('Uhrzeit').AsString := Temp3;
  QryMB256PLUS.ParamByName('Ereignis').AsString := Temp4;
  QryMB256PLUS.ParamByName('Teilnehmer').AsString := Temp5;
  QryMB256PLUS.ParamByName('Bereich').AsString := Temp6;

  QryMB256PLUS.ExecSQL;
  ConMB256PLUS.Commit;

  QRyMB256PLUS.Close;
  QryMB256PLUS.SQL.Text := 'SELECT * FROM MB256PLUS';//'SELECT * FROM MB256PLUS';
  QryMB256PLUS.Open;

  VST.BeginUpdate;
  Daten := TOMB256PLUS.Create;
  QryMB256PLUS.Last;
  with Daten do
  begin
    Daten.ID := QryMB256PLUS.FieldByName('ID').AsInteger;
    Daten.LfdNr := QryMB256PLUS.FieldByName('LfdNr').AsInteger;
    Daten.Datum := QryMB256PLUS.FieldByName('Datum').AsString;
    Daten.Uhrzeit := QryMB256PLUS.FieldByName('Uhrzeit').AsString;
    Daten.Ereignis := QryMB256PLUS.FieldByName('Ereignis').AsString;
    Daten.Teilnehmer := QryMB256PLUS.FieldByName('Teilnehmer').AsString;
    Daten.Bereich := QryMB256PLUS.FieldByName('Bereich').AsString;
  end;
  VST.AddChild(nil, Daten);

          if Pos('Einbruch',Daten.Ereignis)
            or Pos('EINBRUCH',Daten.Ereignis) > 0 then
          begin
          CBAlarme.Items.Add(Daten.Ereignis);
          CBAlarme.ItemIndex := 0;
          CBAlarmeDatum.Items.Add(Daten.Datum);
          CBAlarmeDatum.ItemIndex := 0;
          end;

          if Pos('Störung',Daten.Ereignis)
            or Pos('STÖRUNG',Daten.Ereignis) > 0 then
          begin
          CBStoerungen.Items.Add(Daten.Ereignis);
          CBStoerungen.ItemIndex := 0;
          CBStoerungenDatum.Items.Add(Daten.Datum);
          CBStoerungenDatum.ItemIndex := 0;
          end;

          if Pos('Extern',Daten.Ereignis) > 0 then
          begin
          CBExtern.Items.Add(Daten.Ereignis);
          CBExtern.ItemIndex := 0;
          CBExternDatum.Items.Add(Daten.Datum);
          CBExternDatum.ItemIndex := 0; end;

          if Pos('Intern',Daten.Ereignis) > 0 then
          begin
          CBIntern.Items.Add(Daten.Ereignis);
          CBIntern.ItemIndex := 0;
          CBInternDatum.Items.Add(Daten.Datum);
          CBInternDatum.ItemIndex := 0;
          end;

  VST.ScrollIntoView(VST.GetLast, true);
  VST.EndUpdate;
  QRyMB256PLUS.Close;
  DataMB256plus := '';
end;


procedure TForm1.VSTFreeNode(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
var
  Daten : TOMB256PLUS;
begin
  Daten := TOMB256PLUS(VST.GetNodeData(Node)^);
  Daten.Free;
end;
Leider kann ich mit Haltepunkten nichts anfangen. Da ich bei den vielen bereits gesetzten nichts falsches Enddecken kann.

Hat vieleicht jemand eine Idee.

Gruß und Danke Jens
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 6 von 9   « Erste     456 78     Letzte »    


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 00: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