Delphi-PRAXiS
Seite 6 von 9   « Erste     456 78     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Datenbank in VirtualTreeView anzeigen und auswerten (https://www.delphipraxis.net/130113-datenbank-virtualtreeview-anzeigen-und-auswerten.html)

generic 8. Mär 2009 13:04

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
Zitat:

Zitat von Jens Hartmann
Delphi-Quellcode:
var
  Daten : TOMB256PLUS;
begin
Daten := TOMB256PLUS.Create;

Objekt erzeugen

Zitat:

Zitat von Jens Hartmann
Delphi-Quellcode:
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.

Jens Hartmann 8. Mär 2009 14:52

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
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.

generic 8. Mär 2009 17:16

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
Delphi-Quellcode:
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.

Jens Hartmann 9. Mär 2009 17:51

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
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.

generic 9. Mär 2009 21:02

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
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.

Jens Hartmann 9. Mär 2009 22:37

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
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 10. Mär 2009 16:39

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
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

generic 10. Mär 2009 22:00

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
Sieht ganz gut aus, aber einen müssen wir abziehen, hätten die bei Rosental gesagt.

Du hast ein
Delphi-Quellcode:
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.

Jens Hartmann 10. Mär 2009 22:42

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
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 15. Mär 2009 09:18

Re: Datenbank in VirtualTreeView anzeigen und auswerten
 
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


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:46 Uhr.
Seite 6 von 9   « Erste     456 78     Letzte »    

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 by Thomas Breitkreuz