Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Komponenten dynamisch erzeugen = ok, free = nicht ok (https://www.delphipraxis.net/42250-komponenten-dynamisch-erzeugen-%3D-ok-free-%3D-nicht-ok.html)

torud 16. Mär 2005 11:18


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:
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;
Die Prozedur DestroymyDBKompos soll sich darum kümmern, dass die oben erzeugten Komponenten wieder freigeben werden, damit wieder neue komponenten erzeugt werden können.

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???

jim_raynor 16. Mär 2005 11:40

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 ;)

Orbmu2k 16. Mär 2005 11:41

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;

torud 16. Mär 2005 11:49

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!

Orbmu2k 16. Mär 2005 11:56

Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
 
Ok dann mach aus dem FreeAndNil wieder eine normales Free

torud 16. Mär 2005 12:03

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:
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;
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???

torud 16. Mär 2005 12:27

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:
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;
Trotzdem kommt immer noch die Fehlermeldung, dass er das letzte DB-Feld nicht finden kann.

torud 16. Mär 2005 13:02

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:
DBEdit.DataField:=Table1.FieldList.Strings[i];
schon komisch oder?

Orbmu2k 16. Mär 2005 13:04

Re: Komponenten dynamisch erzeugen = ok, free = nicht ok
 
versuch mal das

Delphi-Quellcode:
  DBEdit.DataField:=Table1.FieldDefs[i].DisplayName;

torud 16. Mär 2005 13:09

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:
          ShowMessage(Table1.FieldDefs[i].DisplayName);
          //DBEdit.DataField:=Table1.FieldDefs[i].DisplayName;
das vorher anzeigen lasse, zeigt er mir die richtigen Feldnamen an. Versuche ich es zuzuweisen, erhalte ich nicht einmal mehr diese Messagebox.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:46 Uhr.
Seite 1 von 2  1 2      

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