![]() |
Wie erstelle ich dynamische forms richtig ?
Guten Tag,
Ich möchte wissen wie man Forms dynamisch richtig und ressourcensparend erstellt. Ich habe das Gefühl das mein momentaner Ansatz viel zu aufwändig / falsch ist. Der Ansatz funktioniert, nur habe ich zweifel das dieser ressourcen spart da jedes Form komplett erstellt wird. Wie ihr im code seht möchte ich jedes dynamisch erstellte Form(child) ansprechen können um jeweilige Parameter definieren zu können. Dazu müssen die childs innerhalb eines containers (scrollbox) positioniert werden. Ist dieser Ansatz korrekt ? Was könnte ich verbessern ?
Delphi-Quellcode:
unit Unit2;
interface uses form_child; type TForm2 = class(TForm) RadioGroup1: TRadioGroup; BitBtn1: TBitBtn; cxTimeEdit1: TcxTimeEdit; DateTimePicker1: TDateTimePicker; JvTimeEdit1: TJvTimeEdit; BitBtn2: TBitBtn; Label1: TLabel; btnCreateChild: TBitBtn; BitBtn3: TBitBtn; cxScrollbox: TcxScrollBox; cxDBTimeEdit1: TcxDBTimeEdit; Edit1: TEdit; dxMemData1: TdxMemData; dxMemData1time: TTimeField; DataSource1: TDataSource; dxLayoutControl1Group_Root: TdxLayoutGroup; dxLayoutControl1: TdxLayoutControl; dxLayoutItem1: TdxLayoutItem; dxLayoutItem2: TdxLayoutItem; dxLayoutGroup1: TdxLayoutGroup; procedure cxButton1Click(Sender: TObject); procedure btnCreateChildClick(Sender: TObject); procedure BitBtn3Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormActivate(Sender: TObject); procedure cxDBTimeEdit1Enter(Sender: TObject); private { Private declarations } ChildArray: array of Tfrm_Child; ChildArraySize: integer; ContainerActualWidth: integer; ContainerActualHeigt: integer; public { Public declarations } end; var Form2: TForm2; implementation procedure TForm2.btnCreateChildClick(Sender: TObject); begin ChildArraySize := (ChildArraySize+1); SetLength(ChildArray, ChildArraySize); ChildArray[ChildArraySize-1] := Tfrm_child.Create(Form2); ChildArray[ChildArraySize-1].Align := alLeft; ChildArray[ChildArraySize-1].Parent := cxScrollbox; ChildArray[ChildArraySize-1].AlignWithMargins := true; ChildArray[ChildArraySize-1].pnlchild.Color := clRed; ChildArray[ChildArraySize-1].pnlchild.Caption := 'ArrayINDEX ='+(ChildArraySize-1).ToString; ChildArray[ChildArraySize-1].Show; end; procedure TForm2.FormCreate(Sender: TObject); begin ChildArraySize := 0; ContainerActualWidth := cxScrollbox.Width; ContainerActualHeigt := cxScrollbox.Height; end; |
AW: Wie erstelle ich dynamische forms richtig ?
Moin...:P
Zitat:
Zum Thema: Im Prinzip machst du es richtig. Ich würde aber statt dem array eine TObjectList<TForm> oder ein TObjectDictionary<string, TForm> nehmen. Über die Freigabe der Forms kann man diskutieren. Du verwendest Form2 als Owner. Du könntest auch die Liste die Forms freigeben lassen. (OwnObjects). Das ist hilfreich wenn man einzelne Forms aus der Liste entfernt. |
AW: Wie erstelle ich dynamische forms richtig ?
Zitat:
Könntest du mir ein Beispiel schreiben wie du das meinst mit der TObjectList und TObjectDictionary ? |
AW: Wie erstelle ich dynamische forms richtig ?
Zitat:
Zitat:
Hausaufgaben: ![]() ![]() Frage: Wo ist der Unterschied zwischen den beiden? |
AW: Wie erstelle ich dynamische forms richtig ?
Zitat:
TObjectDictionary überprüft automatisch ob ein TObject noch gebraucht wird oder nicht und gibt dies automatisch frei wenn es nicht mehr gebraucht wird. Hmm... also ist TObjectList ein Array von Objekten mit dem unterschied wenn ich etwas aus der TObjectList entferne wird es auch automatisch freigegeben. Mit meinem Array oben bin ich selber verantwortlich das ALLE TObjects wieder freigegeben werden die ich erstellt habe. Korrekt ? |
AW: Wie erstelle ich dynamische forms richtig ?
Zitat:
Zitat:
Delphi-Quellcode:
unit Unit2;
interface uses System.Classes, System.Generics.Collections, System.Generics.Defaults, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls; form_child; // :-) entspricht nicht dem Styleguide...besser FormChild type TForm2 = class(TForm) btnCreateChild: TButton; lblList: TLabel; lblDict: TLabel; lblDict2: TLabel; procedure btnCreateChildClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private FList: TObjectList<TForm>; FDictionary: TObjectDictionary<string, TForm>; public end; var Form2: TForm2; implementation procedure TForm2.FormCreate(Sender: TObject); begin FList := TObjectList<TForm>.Create(True); // True gibt die Objekte selbstständig frei FDictionary := TObjectDictionary<string, TForm>.Create([doOwnsValues]); // doOwnValues gibt die Objekte (Value) selbstständig frei end; procedure TForm2.FormDestroy(Sender: TObject); begin FList.Free; FDictionary.Free; end; procedure TForm2.btnCreateChildClick(Sender: TObject); var I: Integer; Child: TForm; TempForm: TForm; begin for I := 0 to 2 do begin Child := Tfrm_child.Create(nil); // :-) entspricht nicht dem Styleguide...besser TfrmChild Child.Name := 'Child' + IntToStr(I); Child.Align := alLeft; Child.Parent := cxScrollbox; Child.AlignWithMargins := True; Child.pnlchild.Color := clRed; Child.pnlchild.Caption := 'ArrayINDEX = ' + IntToStr(Integer); FList.Add(Child); FDictionary.Add(Child.Name, Child); Child.Show; end; lblList.Caption := 'Name des ersten Eintrages: ' + FList[0].Name; lblDict.Caption := 'Name des 2. Eintrages im Dictionary: ' + FDictionary.Items['Child2'].Name; // Wenn man nicht weiß ob der Schlüssel existiert FDictionary.TryGetValue('Child2', TempForm); if Assigned(TempForm) then begin lblDict.Caption := 'Name des 3. Eintrages im Dictionary: ' + TempForm.Name; end else begin lblDict.Caption := 'Name des 3. Eintrages im Dictionary: nicht gefunden'; end; end; end.
Delphi-Quellcode:
object Form2: TForm2
Left = 0 Top = 0 Caption = 'Form2' ClientHeight = 299 ClientWidth = 635 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False OnCreate = FormCreate OnDestroy = FormDestroy PixelsPerInch = 96 TextHeight = 13 object lblList: TLabel Left = 48 Top = 96 Width = 26 Height = 13 Caption = 'lblList' end object lblDict: TLabel Left = 48 Top = 120 Width = 28 Height = 13 Caption = 'lblDict' end object lblDict2: TLabel Left = 48 Top = 144 Width = 34 Height = 13 Caption = 'lblDict2' end object btnCreateChild: TButton Left = 40 Top = 40 Width = 75 Height = 25 Caption = 'Create' TabOrder = 0 OnClick = btnCreateChildClick end end |
AW: Wie erstelle ich dynamische forms richtig ?
Zitat:
|
AW: Wie erstelle ich dynamische forms richtig ?
Zitat:
![]() Zitat:
|
AW: Wie erstelle ich dynamische forms richtig ?
Du musst die Größe des Arrays nicht als Feld/Variable im Form "speichern".
Die Funktion Low liefert den ersten Index des Arrays. High den letzten. Length gibt die Größe aus. Mit Length kannst du übrigens auch die Länge eines Strings ermitteln. Ein String ist intern auch nur ein Array.
Delphi-Quellcode:
Ich würde statt dem Array aber eine TObjectList verwenden.
TForm2 = class(TForm)
... procedure btnCreateChildClick(Sender: TObject); procedure FormCreate(Sender: TObject); private ChildArray: array of Tfrm_Child; ContainerActualWidth: integer; ContainerActualHeigt: integer; end; ... procedure TForm2.btnCreateChildClick(Sender: TObject); var Index: Integer; begin // Array vergrößern SetLength(ChildArray, Length(ChildArray) + 1); // Letzten und damit aktuellen Index temporär "speichern" // damit nicht ständig High aufgerufen werden muss. Index := High(ChildArray); // Form erstellen ChildArray[Index] := Tfrm_child.Create(Form2); ChildArray[Index].Parent := cxScrollbox; ChildArray[Index].Align := alLeft; ChildArray[Index].AlignWithMargins := True; ChildArray[Index].pnlchild.Color := clRed; ChildArray[Index].pnlchild.Caption := 'ArrayINDEX =' + IntToStr(Index); ChildArray[Index].Show; end;
Delphi-Quellcode:
uses
..., ContNrs; ... TForm2 = class(TForm) ... procedure btnCreateChildClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormClose(Sender: TObject); private FChildList: TObjectList; protected procedure CreateChildList; procedure DestroyChildList; function NewChildForm: Integer; end; ... procedure TForm2.CreateChildList; begin // Liste erstellen // Wird bei Create kein Parameter oder True übergeben // verwaltet die Liste alle eingetragenen Objekte // d. h. wenn die Liste freigegeben oder ein Eintrag // gelöscht wird, wird die / das Form automatisch // freigegeben FChildList := TObjectList.Create; // Wenn du False übergibst bist du selbst // verantwortlich die einzelnen Forms/Einträge // freizugeben: //FChildList := TObjectList.Create(False); end; procedure TForm2.DestroyChildList; begin // Wenn OwnsObjects False ist, // musst du durch alle Einträge iterieren // und die Objekte selbst freigeben bevor // die Liste zerstört wird. Das würde so aussehen: for FormIndex := FChildList.Count - 1 downto 0 do FreeAndNil(FChildList[FormIndex]); // Da in CreateChildList nicht False übergeben wurde // ist dies nicht nötig. FreeAndNil(FChildList); end; function TForm2.NewChildForm: Integer; var NewForm: Tfrm_child; begin // Form erzeugen NewForm := Tfrm_child.Create(Self); try // Form der Liste hinzufügen // Add gibt den Index des neuen Eintrags zurück. Result := FChildList.Add(NewForm); // Form Eigenschaften setzen NewForm.Parent := cxScrollbox; NewForm.Align := alLeft; NewForm.AlignWithMargins := True; NewForm.pnlchild.Color := clRed; NewForm.pnlchild.Caption := 'ArrayINDEX =' + IntToStr(Result); NewForm.Show; except // Wenn ein Fehler auftritt wird -1 zurückgegeben. // Sinnvoller wäre es den Fehler zu "verarbeiten". Result := -1; end; end; procedure TForm2.btnCreateChildClick(Sender: TObject); var Index: Integer; begin // Funktion aufrufen um Form zu erstellen // Die Funktion gibt den Index des neuen Forms // zurück. Den kannst du evtl. brauchen wenn nachträglich // das Form geändert werden soll. // Wird -1 zurückgegeben konnte das Form nicht erstellt oder // nicht der Liste hinzugefügt werden. Index := Self.NewChildForm; // Überprüfen ob das Form erstellt // wurde, ggf. Meldung anzeigen. if Index = -1 then ShowMessage('Das Form konnte nicht erstellt werden!') else ShowMessage('Das Form wurde erfolgreich erstellt.'); // Auf das Form via Index zugreifen Tfrm_child(FChildList[Index]).Caption := 'Hallo Welt'; end; procedure TForm2.FormCreate(Sender: TObject); begin // Liste erzeugen Self.ChildListCreate; end; procedure TForm2.FormDestroy(Sender: TObject); begin // Liste freigeben wenn das Form zerstört wird. // Das kann man alternativ auch im OnClose machen. Self.ChildListDestroy; end; |
AW: Wie erstelle ich dynamische forms richtig ?
Moin...:P
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:54 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