![]() |
Komponenten dynamisch erzeugen = ok, free = nicht ok
Hallo Leute!
Ich habe die Suche bedient und einiges zu diesem Thema gefunden. Leider hat es nichts gebracht. Mit folgender Prozedure erzeuge ich auf einer Scrollbox dynamisch DBEdits und Labels, nachdem ich eine Datenbank geladen habe. Nicht unbedingt schön, aber es funzt.
Delphi-Quellcode:
procedure TForm1.TrytoCreateDBFields; //dynamisches erzeugen
var i:integer; DBEdit:TDBEdit; Labels:TLabel; scr_dbfields:TScrollBox; begin scr_dbfields.Free; scr_dbfields := TScrollbox.Create(self); scr_dbfields.Parent:=TabSheet7; scr_dbfields.Align:=alClient; with scr_dbfields do begin for i:=0 to Table1.FieldCount-1 do begin case Table1.Fields.Fields[i].DataType of ftString,ftInteger, ftAutoInc, ftSmallint, ftFloat,ftWord : begin //label erzeugen Labels:= TLabel.Create(self); Labels.Parent := scr_dbfields; Labels.Left :=10; Labels.Top := i * 30; Labels.Caption:=Table1.FieldList.Strings[i]; //dbfeld erzeugen DBEdit:= TDBEdit.Create(self); DBEdit.Parent := scr_dbfields; DBEdit.Left :=100; DBEdit.Top := i * 30; DBEdit.DataSource:=DataSource1; DBEdit.Name:=Table1.FieldList.Strings[i]; DBEdit.DataField:=Table1.FieldList.Strings[i]; end; end; end; end; end;
Delphi-Quellcode:
procedure TForm1.DestroymyDBKompos; //dynamisches freigeben
var i:integer; begin i:= 0; while i<scr_dbfields.parent.ComponentCount do if (scr_dbfields.parent.Components[i] is TDBEdit) or ((scr_dbfields.parent.Components[i] is TLabel)) then scr_dbfields.parent.Components[i].Free else Inc(i); end; Wenn ich nun auf eine FileListBox doppelt klicke und versuche eine neue DB zu öffnen erhalte ich immer wieder eine Fehlermeldung.
Delphi-Quellcode:
Die Prozedur DestroymyDBKompos soll sich darum kümmern, dass die oben erzeugten Komponenten wieder freigeben werden, damit wieder neue komponenten erzeugt werden können.
procedure TForm1.FileListBox1DblClick(Sender: TObject);
begin Table1.Active:=False; Table1.DatabaseName:=DirectoryListBox1.Directory; Table1.TableName:=FileListBox1.Items.Strings[FileListBox1.ItemIndex]; DestroymyDBKompos; //zerstören der kompos //scr_dbfields.Free; ShowMessage('kaput'); Table1.Active:=True; ed_header.Text:=FileListBox1.Items.Strings[FileListBox1.ItemIndex]; TrytoCreateDBFields; //neues generieren der kompos end; Das Ganze funktioniert nur einmal nach dem Programmstart. Wenn ich dann eine andere DB laden willerhalte ich immer wieder eine Fehlermeldung, dass irgendein DB-Feld nicht gefunden wurde. Das passiert aber nur, wenn ich DestroymyDBKompos oder/und TrytoCreateDBFields versuche zu benutzen. Was mache ich denn da falsch??? |
Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
Du darfst nicht scr_dbfields.Free machen. scr_dbfields ist doch undefiniert und dann dort den Speicher freigeben? Das ist ganz böse und an dieser Stelle auch überflüssig, da du noch gar kein Objekt hast. Eventuell solltest du es als globale Variable definieren und mit nil initsialisieren.
Kann es sein dass du dbfields schon als Globale Variable hast? Dann sollest du die Variable in TrytoCreateDBFields löschen ;) |
Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
versuchs mal so ... (ungetestet)
Delphi-Quellcode:
procedure TForm1.DestroymyDBKompos; //dynamisches freigeben
var i:integer; begin for i := scr_dbfields.parent.ComponentCount-1 downto 0 do if (Assigned(cr_dbfields.parent.Components[i])) and ((scr_dbfields.parent.Components[i] is TDBEdit) or (scr_dbfields.parent.Components[i] is TLabel)) then FreeAndNil(scr_dbfields.parent.Components[i]); end; |
Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
Danke für die Infos!
Bei dem Codeversuch habe ich eine Fehlermeldung erhalten, die besagt, dass das "Konstantenobjekt nicht als Var-Parameter weitergegeben werden kann". Diese Meldung bezieht sich auf die letzte zeile FreeandNil... und @ jim scr_dbfields ist doch die Scrollbox, auf der ich die Kompos ablege. Ich dachte eigentlich, dass es reichen könnte, wenn ich diese Scrollbox freigeben und sich das Programm der Kompos darauf selbst entledigt...Dem war nicht so. Warum ist denn scr_dbfields undefiniert? und, TrytoCreateDBFields ist eine Prozedur und keine Variable! |
Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
Ok dann mach aus dem FreeAndNil wieder eine normales Free
|
Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
ok, nun mecker zumindest nicht mehr der Compiler, beim Erstellen der exe.
Aber ich bekomme immer noch eine Fehlermeldung. Und zwar versucht das Programm beim Zerstören noch auf Datenbankbestandteile zuzugreifen, vermute ich zumindest, denn in der Fehlermeldung steht immer wieder, dass "Das Feld Text wurde nicht gefunden" Dies ist in dem Fall das letzte Datenbankfeld. Diese Meldung kommt nur, wenn ich versuche DestroymyDBKompos ausführen zu lassen. Wenn ich mir davor eine Message anzeigen lasse ist alles ok. Und noch ein kleines Problem. Ich habe die Prozedure ein wenig umgebaut, weil ich einfach checken wollte, wo der Fehler liegen könnte.
Delphi-Quellcode:
Die Messagebox erhalte ich nicht, denn es kommt vorher die Meldung, wie oben beschrieben. Hm, muss ich die Komponenten vorher noch von der DB lösen???
procedure TForm1.DestroymyDBKompos;
var i:integer; begin i:= 0; for i := scr_dbfields.parent.ComponentCount-1 downto 0 do if (Assigned(scr_dbfields.parent.Components[i])) and ((scr_dbfields.parent.Components[i] is TDBEdit) or (scr_dbfields.parent.Components[i] is TLabel)) then begin ShowMessage(scr_dbfields.parent.Components[i].Name); scr_dbfields.parent.Components[i].Free; end; end; |
Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
Ich habe beim Debuggen noch herausbekommen, dass obwohl mindestens 3 Komponenten auf der Scollbox vorhanden sind der scr_dbfields.parent.ComponentCount = 0 ist. Kann es sein, dass die Obejkte nicht korrekt als Childs zugewiesen werden und dadurch die Probleme entstehen?
Zumindest habe ich nun die Prozedur zum Erstellen so abgeändert, dass der Count hinhaut und das die Controls dem scr_dbfields als Childs zugewiesen werden.
Delphi-Quellcode:
Trotzdem kommt immer noch die Fehlermeldung, dass er das letzte DB-Feld nicht finden kann.
procedure TForm1.TrytoCreateDBFields;
var i:integer; DBEdit:TDBEdit; Labels:TLabel; scr_dbfields:TScrollBox; begin scr_dbfields.Free; scr_dbfields := TScrollbox.Create(TabSheet7); scr_dbfields.Parent:=TabSheet7; scr_dbfields.Align:=alClient; with scr_dbfields do begin for i:=0 to Table1.FieldCount-1 do begin case Table1.Fields.Fields[i].DataType of ftString,ftInteger, ftAutoInc, ftSmallint, ftFloat,ftWord : begin //label erzeugen Labels:= TLabel.Create(scr_dbfields); Labels.Parent := scr_dbfields; Labels.Left :=10; Labels.Width:=85; Labels.Alignment:=taRightJustify; Labels.Top := (i * 30)+3; Labels.Caption:=Table1.FieldList.Strings[i]; //dbfeld erzeugen DBEdit:= TDBEdit.Create(scr_dbfields); DBEdit.Parent := scr_dbfields; DBEdit.Left :=100; DBEdit.Top := i * 30; DBEdit.DataSource:=DataSource1; DBEdit.Name:=Table1.FieldList.Strings[i]; DBEdit.DataField:=Table1.FieldList.Strings[i]; ShowMessage(inttostr(scr_dbfields.ComponentCount)) end; end; end; end; end; |
Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
An Alle, die es noch interessiert!
Das Problem ist nicht das löschen der Controls, sondern tritt erst beim Zuweisen des DataFields auf. Wenn ich diese Zeile auskommentiere wird alles immer korrekt erstellt und gelöscht. Das Problem ist, dass diese Zuweisung aber für die Anbindung an die DB wichtig ist. aus der Prozedur TrytoCreateDBFields
Delphi-Quellcode:
schon komisch oder?
DBEdit.DataField:=Table1.FieldList.Strings[i];
|
Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
versuch mal das
Delphi-Quellcode:
DBEdit.DataField:=Table1.FieldDefs[i].DisplayName;
|
Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
Danke für den Tipp, aber das Problem ist das GLEICHE!
Kann es sein, dass ich vorher noch die Fieldlist löschen muss? Das komische ist, wenn ich mir
Delphi-Quellcode:
das vorher anzeigen lasse, zeigt er mir die richtigen Feldnamen an. Versuche ich es zuzuweisen, erhalte ich nicht einmal mehr diese Messagebox.
ShowMessage(Table1.FieldDefs[i].DisplayName);
//DBEdit.DataField:=Table1.FieldDefs[i].DisplayName; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:15 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