![]() |
Re: Datenbank in VirtualTreeView anzeigen und auswerten
Zitat:
Zitat:
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:
Was macht deine "Initialize" Daten Funktion?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); 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. |
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. |
Re: Datenbank in VirtualTreeView anzeigen und auswerten
Delphi-Quellcode:
ist an der Stelle auch falsch.
VST.AddChild(nil,Daten);
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. |
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:
Das müssten alle Funktionen sein.
//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; |
Re: Datenbank in VirtualTreeView anzeigen und auswerten
Delphi-Quellcode:
Wofür brauchst du da ein neues Daten Objekt? Was passiert damit?
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;
Delphi-Quellcode:
So jetzt weisst du hier einen nicht initialisierten Objekt dazu zu.
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; 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. |
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; |
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:
Ich bedanke mich schon mal, und hoffe auf Eure antworten.//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; Gruß Jens |
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:
doppelt.
VST.NodeDataSize := SizeOf(TOMB256PLUS);
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. |
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:
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).
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;
Delphi-Quellcode:
Was für mich bedeuten tut, will ich die ID im VST sehen, muss ich diese ja aus der Datenbankabfragen, Oder?
//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;
Delphi-Quellcode:
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.
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; 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; |
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:
Leider kann ich mit Haltepunkten nichts anfangen. Da ich bei den vielen bereits gesetzten nichts falsches Enddecken kann.
{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; Hat vieleicht jemand eine Idee. Gruß und Danke Jens |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:46 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 by Thomas Breitkreuz