Wie realisiere ich am besten sich wiederholende "Komponente"?

Für Fragen von Einsteigern und Programmieranfängern...
Benutzeravatar
photor
Beiträge: 507
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 3.2 (Gtk2) FPC 3.2.2
CPU-Target: 64Bit

Wie realisiere ich am besten sich wiederholende "Komponente"?

Beitrag von photor »

Hallo Forum,

ich hoffe, der angehängte Screenshot zeigt das wesentliche. Es gibt (mittlerweile) 3 gleiche sich wiederholende TGroupBoxes mit diversen gleichen Elementen in gleicher Anordnung. Das schreit gerade zu danach, das Design bzw. die Anordnung einmal festzulegen und dann im Programm 3-mal zu erzeugen (jeweils mit anderem Namen, um es mit dann entsprechenden Daten zu füllen).[1] Jede anstehende Änderung auf allen 3 parallel zu machen, ist mir zu aufwändig (und widerstrebt der "Programmierer-Ehre").

Daher frage ich mich, wie ich das am geschicktesten bewrkstellige. Meine Ideen:
  • TPanel, TFrame, TBevel ... welche davon ist überhaupt - und wenn ja, am besten - geeignet?
  • geht das in Form einer Klasse, die dann im Form-Designe (oder auch im Code) eingebunden wird?
  • gleich eine eigene Komponent definieren (ist aber auch Neuland)?
Das Wiki hat mich eher verwirrt. Deshalb würde ich mich über ein paar Anregungen oder Beispiele freuen.

Ciao,
Photor


[1]bis jetzt habe ich das von Hand im Form-Editor gemacht, da das Programm halt so gewachsen ist.

PS: Bild scheint leider nicht richtig mit rüberzukommen - Sorry.
Dateianhänge
Bildschirmfoto vom 2025-03-19 19-11-31.png
Bildschirmfoto vom 2025-03-19 19-11-31.png (18.6 KiB) 4239 mal betrachtet
Zuletzt geändert von photor am Fr 21. Mär 2025, 17:35, insgesamt 1-mal geändert.

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 359
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Wie realisiere ich am besten sich wiederholende "Komponnente"?

Beitrag von Jorg3000 »

Hi!
Ich mache soetwas immer als TFrame, weil man dann auch eine eigene Unit dazu hat.
Das Frame erzeuge ich dann allerdings per Programm im Ziel-Form, weil ein Einfügen per IDE zu Problemen führen kann, wenn man am Frame Eigenschaften ändert.

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 580
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Wie realisiere ich am besten sich wiederholende "Komponnente"?

Beitrag von Niesi »

Das "Bild" ist bei mir nur eine Schraffur.

Möchtest Du die Komponenten in Forms platzieren können oder dürfen es jeweils eigene Forms sein?
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6762
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Wie realisiere ich am besten sich wiederholende "Komponnente"?

Beitrag von af0815 »

Ich arbeite extensiv mit Frames, das wäre auch mein Vorschlag. Vor allen kann man die Optik und die Funktionen sehr gut Kapseln. Nur bitte nicht statisch, ich verwende es nur dynamisch, da die IDE da einige ... äh ..... Besonderheiten hat. War bei Delphi früher auch so.

Aber es geht auch anders, weil viele Wege führen nach Rom.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

wp_xyz
Beiträge: 5129
Registriert: Fr 8. Apr 2011, 09:01

Re: Wie realisiere ich am besten sich wiederholende "Komponnente"?

Beitrag von wp_xyz »

Schaue dir als Beispiel den ChartEditor in dem gleichnamigen Verzeichnis in components/tachart/demo der Lazarus-Installation an. Da wird intensiv mit Frames gearbeitet, teilweise mit Frames in Frames (in Frames).

Mathias
Beiträge: 6899
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Wie realisiere ich am besten sich wiederholende "Komponnente"?

Beitrag von Mathias »

e. Es gibt (mittlerweile) 3 gleiche sich wiederholende TGroupBoxes mit diversen gleichen Elementen in gleicher Anordnung. Das schreit gerade zu danach, das Design bzw. die Anordnung einmal festzulegen und dann im Programm 3-mal zu erzeugen
Ich würde es einfach dynamisch in einer forto schleife lösen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Wie realisiere ich am besten sich wiederholende "Komponnente"?

Beitrag von Zvoni »

Mein Ansatz wäre per eigener Klasse (Ob jetzt "eingebettet" in einem TFrame oder was auch immer mal aussen vor).
Die Klasse würde auch alle Event-Handler haben (Hier würde dann das "Sender"-Argument wichtig werden).

GGfs. noch den Constructor der Form "overriden".
In der Form selbst würde ich dann diese "Komponente" in einer TFPList (oder Array, was auch immer) sammeln.
Diese Klasse ausgelagert in ihrer eigenen Unit wäre dann auch für alle anderen Formen verwendbar
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Benutzeravatar
photor
Beiträge: 507
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 3.2 (Gtk2) FPC 3.2.2
CPU-Target: 64Bit

Re: Wie realisiere ich am besten sich wiederholende "Komponnente"?

Beitrag von photor »

Hallo Forum,

zuerst einmal: "Boar! Da ist ja einiges an Rückmeldungen gekommen. Danke!".

ich fange mal oben an.

Bild sehe ich leider auch nur als Schrafur; keinen Ahnung warum. HAtte überlegt, es nochmal zu versuchen. Aber bei der Menge an Input braucht es kein Bild, um klarzumachen, worum es mir geht.
Jorg3000 hat geschrieben: Mi 19. Mär 2025, 21:07 Ich mache soetwas immer als TFrame, weil man dann auch eine eigene Unit dazu hat.
Das Frame erzeuge ich dann allerdings per Programm im Ziel-Form, weil ein Einfügen per IDE zu Problemen führen kann, wenn man am Frame Eigenschaften ändert.


TFrame war auch meine Idee. Aber das habe ich nicht wirklich hinbekommen und wohl auch noch nicht richtig verstanden. Ob ich den Frame dann so programmiert bekomme, muss ich probieren.
af0815 hat geschrieben: Mi 19. Mär 2025, 21:31 Ich arbeite extensiv mit Frames, das wäre auch mein Vorschlag. Vor allen kann man die Optik und die Funktionen sehr gut Kapseln. Nur bitte nicht statisch, ich verwende es nur dynamisch, da die IDE da einige ... äh ..... Besonderheiten hat. War bei Delphi früher auch so.

Aber es geht auch anders, weil viele Wege führen nach Rom.
Hm. OK. Mag sein, dass das der Grund ist, dass meine Versuche nichts nutzbares gebracht haben. War jedenfalls von meinen ersten Versuchen sehr verwirrt - und gefrustet.
wp_xyz hat geschrieben: Mi 19. Mär 2025, 22:42 Schaue dir als Beispiel den ChartEditor in dem gleichnamigen Verzeichnis in components/tachart/demo der Lazarus-Installation an. Da wird intensiv mit Frames gearbeitet, teilweise mit Frames in Frames (in Frames).
DAnke, für den "Link". Ich hatte schon nach Beispielen für Frames gesucht. Aber explizit gab es da nichts (oder ich habe vorbei geklickt). Aber das ist mal ein realisiertes Projekt, von dem man lernen kann.
Mathias hat geschrieben: Do 20. Mär 2025, 08:23 Ich würde es einfach dynamisch in einer forto schleife lösen.
Wenn man die Frames per Programmcode definiert, ja. Dann nach die Parameter (Namen, StringGrid-Cols/Rows etc) setzen und positionieren.
Zvoni hat geschrieben: Do 20. Mär 2025, 08:37 Mein Ansatz wäre per eigener Klasse (Ob jetzt "eingebettet" in einem TFrame oder was auch immer mal aussen vor).
Die Klasse würde auch alle Event-Handler haben (Hier würde dann das "Sender"-Argument wichtig werden).
DAs war auch eine Idee als "große Lösung". Wäre was wie eine Art neue Komponente. Aber das ist ganz bestimmt Neuland für mich.
Zvoni hat geschrieben: Do 20. Mär 2025, 08:37 GGfs. noch den Constructor der Form "overriden".
In der Form selbst würde ich dann diese "Komponente" in einer TFPList (oder Array, was auch immer) sammeln.
Diese Klasse ausgelagert in ihrer eigenen Unit wäre dann auch für alle anderen Formen verwendbar
Das wäre die "ganz große Lösung" (aber fein und konsequent). Da ich aber nicht denke, dass diese Komponente noch in einem weiteren Projekt auftauchen wird (zu spezielles Tool), wäre das wohl zu groß - und damit die erst der nächste Schritt.

Noch mal Danke für den Input. Qunintessenz: TFrame ist schon das richtige Mittel. Ich grabe mich mal durch das alles und melde mich mit Fragen oder dem Erfolg wieder.

Ciao,
Photor

Mathias
Beiträge: 6899
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Wie realisiere ich am besten sich wiederholende "Komponnente"?

Beitrag von Mathias »

Ich scheue mich so wieso nicht mehr, Komponenten dynamisch zu erstellen. Vielfach ist dies der besser Weg als das *klickibunti*.
Nur wen man schon eine Button Reihe hat, fährt man dynamisch vielfach besser.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
photor
Beiträge: 507
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 3.2 (Gtk2) FPC 3.2.2
CPU-Target: 64Bit

Re: Wie realisiere ich am besten sich wiederholende "Komponente"?

Beitrag von photor »

Hallo Forum,

habe ein einfaches Beispiel versucht. Und - wie zu erwarten - hänge ich schon.

Ich habe einen Frame erstellt (eine TGroupBox als Rand drumrum, TLabels, TEdits und ein TStringGrid):

Code: Alles auswählen

unit PadResultsFrm;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, StdCtrls, Grids;

type

  { TPadResultsFrame }

  TPadResultsFrame = class(TFrame)
    PadResultsGrpBx: TGroupBox;
    Label4: TLabel;
    MaxPadPressureEdt: TEdit;
    Label2: TLabel;
    Label3: TLabel;
    PadAreaEdt: TEdit;
    Label1: TLabel;
    PadResultsStrgGrd: TStringGrid;

  private

  public
//    constructor Create(AOwner: TComponent);  override;


  end;

implementation

{$R *.lfm}

//constructor TPadResultsFrame.Create(AOwner: TComponent);
//begin
//  inherited;
//end;

end.
Per Hand im FormEditor ließ sich dieses auch auf dem MainForm platzieren (auch mehrfach!). Aber ich habe schon gemerkt, dass das eine hakelige Angelegenheit wird. Also den Rat befolgt, den Frame im Code zu erstellen und zu platzieren.

Code: Alles auswählen

unit TestFrames_MainForm;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Grids,
  PadResultsFrm;

type

  { TTestFramesMainForm }

  TTestFramesMainForm = class(TForm)
    Button1: TButton;
    Label4: TLabel;
    MaxPadPressureEdt: TEdit;
    Label3: TLabel;
    PadAreaEdt: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    OriginalGrpBx: TGroupBox;
    OkBtn: TButton;
    DataPadsStrgGrd: TStringGrid;

    procedure CloseBtnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);

  private

  public

    TopPadResultsFrm, BottomPadResultsFrm, RadialPadResultsFrm: TPadResultsFrame;

  end;

var
  TestFramesMainForm: TTestFramesMainForm;

implementation

{$R *.lfm}

{ TTestFramesMainForm }


procedure TTestFramesMainForm.CloseBtnClick(Sender: TObject);
begin
  Close;
end;


procedure TTestFramesMainForm.FormCreate(Sender: TObject);
begin
  TopPadResultsFrm := TPadResultsFrame.Create(self);
  TopPadResultsFrm.Parent := self;
  TopPadResultsFrm.PadResultsGrpBx.Caption:= 'Top Pads';
  TopPadResultsFrm.Left := 400;
  TopPadResultsFrm.Top := 20;

  //BottomPadResultsFrm := TPadResultsFrame.Create(self);
  //BottomPadResultsFrm.Parent := self;
  //BottomPadResultsFrm.PadResultsGrpBx.Caption:= 'Bottom Pads';
  //BottomPadResultsFrm.Left := 700;
  //BottomPadResultsFrm.Top := 20;
  //
  //RadialPadResultsFrm := TPadResultsFrame.Create(self);
  //RadialPadResultsFrm.Parent := self;
  //RadialPadResultsFrm.PadResultsGrpBx.Caption:= 'Radial Pads';
  //RadialPadResultsFrm.Left := 1000;
  //RadialPadResultsFrm.Top := 20;

end;

end.

So, wie oben gezeigt, funktioniert es: ein Frame wird erzeugt.

Versuche ich aber, einen zweiten und dritten daneben zu platzieren, bekomme ich die Meldung, dass PadResultsFrame bereits existiert.

Irgendetwas habe ich an der Stelle nicht bzw. falsch verstanden. Von anderen Komponenten kann ich ja auch mehrere erzeugen. Hier sollen es 3 werden, die jeweils über die zugewiesenen Variablen angesprochen werden sollen, um die Labels, Edits und StringGrid zu setzen. (Im eigentlichen Programm sollen die 3 Einheiten auf einem TPageControl-Tab liegen.

Ist das so möglich? Bzw. wie wäre es möglich?

Ciao,
Photor

Sieben
Beiträge: 289
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: Wie realisiere ich am besten sich wiederholende "Komponente"?

Beitrag von Sieben »

Call 'em names! Nein, nicht beschimpfen, aber gib mal jedem zusätzlich zu den anderen Eigenschaften auch einen eindeutigen Namen.

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 359
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Wie realisiere ich am besten sich wiederholende "Komponente"?

Beitrag von Jorg3000 »

Wenn man keinen Komponentennamen benötigt (i.d.R. nicht), genügt es nach jedem Create den .Name:=''; zu setzen.

wp_xyz
Beiträge: 5129
Registriert: Fr 8. Apr 2011, 09:01

Re: Wie realisiere ich am besten sich wiederholende "Komponente"?

Beitrag von wp_xyz »

Am besten ist es bei zur Laufzeit erzeugten Komponenten, den Namen leer zu lassen. Leider wird jedem Frame automatisch beim Erzeugen ein Name zugewiesen, du musst daher vor dem Einfügen in den Parent den Namen wieder löschen.

In der Anlage ein kleines Beispiel, an dem du das Wesentliche vielleicht leichter erkennst als an dem umfangreichen ChartEditor.
Dateianhänge
frames.zip
(3 KiB) 76-mal heruntergeladen

Benutzeravatar
photor
Beiträge: 507
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux: L 3.2 (Gtk2) FPC 3.2.2
CPU-Target: 64Bit

Re: Wie realisiere ich am besten sich wiederholende "Komponente"?

Beitrag von photor »

Jorg3000 hat geschrieben: Fr 21. Mär 2025, 19:21 Wenn man keinen Komponentennamen benötigt (i.d.R. nicht), genügt es nach jedem Create den .Name:=''; zu setzen.
Uff. Du hast Recht! :shock:

So funtioniert's:

Code: Alles auswählen

procedure TTestFramesMainForm.FormCreate(Sender: TObject);
begin
  TopPadResultsFrm := TPadResultsFrame.Create(self);
  TopPadResultsFrm.Name := 'TopPadResults';
  TopPadResultsFrm.Parent := self;
  TopPadResultsFrm.PadResultsGrpBx.Caption:= 'Top Pads';
  TopPadResultsFrm.Left := 400;
  TopPadResultsFrm.Top := 20;

  BottomPadResultsFrm := TPadResultsFrame.Create(self);
  BottomPadResultsFrm.Name := 'BottomPadResults';
  BottomPadResultsFrm.Parent := self;
  BottomPadResultsFrm.PadResultsGrpBx.Caption:= 'Bottom Pads';
  BottomPadResultsFrm.Left := 700;
  BottomPadResultsFrm.Top := 20;

end;
Muss ich noch 'nen Moment drüber nachdenken.

Danke.
Photor

wp_xyz
Beiträge: 5129
Registriert: Fr 8. Apr 2011, 09:01

Re: Wie realisiere ich am besten sich wiederholende "Komponente"?

Beitrag von wp_xyz »

Wofür brauchst du den Namen bei einer zur Laufzeit erzeugten Komponente? Du hast doch den Variablennamen (TopPadResultsFrm, BottomPadresultsFrm), um auf die Komponente zuzugreifen. Das ist viel schneller als die Komponente mit "FindComponent" auf der Basis von "Name" erst zu suchen.

Antworten