Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Ansprechen von während Laufzeit erzeugter Komponenten (https://www.delphipraxis.net/210142-ansprechen-von-waehrend-laufzeit-erzeugter-komponenten.html)

Kurt Wallander 7. Mär 2022 17:00

Delphi-Version: 10.4 Sydney

Ansprechen von während Laufzeit erzeugter Komponenten
 
Hallo Delphianer,
mein Problem:
Schritt 1: erzeuge in Form1.create insgesamt 81 Labels während der Laufzeit. Alles i. O.
Schritt 2: Lesen Daten von einer Datei in ein Integer-Array[1..9,1..9] ein. Alles i. O.
Schritt 3: Will nun (falls F[i,k]>0) ein Label ansprechen und beschriften. Wie kann ich dieses Label ansprechen? Der Compiler kennt ja dieses Label nicht, da es zur Entwurfszeit nicht existiert.
Allen Labels ist die gleiche onClick-prozedur zugeordnet. Diese soll ebenfalls das Label beschriften. Die Labels könnten über ihren Namen angesprochen werden.
Habe Hilfen und Tutorials tonnenweise gelesen, aber dort läßt man sich nur zum Generieren der Komponenten aus und nicht wie ich von einer anderen prozedur der gleichen Form diese dann anspreche/aufrufen.
Für nützliche Hinweise bin ich dankbar.
Im Schritt 1 klappt lediglich die Farbzuordnung nicht.

Delphi-Quellcode:
   .
   .
   .
   i:=1;
   while i<= 9 do
   begin
      j:=1;
      while j<= 9 do
      begin
         n_lbl:='Feld'+IntToStr(j)+IntToStr(i);
         begin
            ALabel:=TLabel.Create(Self);
            ALabel.Name := n_lbl;
            ALabel.Left := left_M+(i-1)*sw-5;
            ALabel.Top := top_m+(j-1)*sw-5;
            ALabel.height:=sw-12;
            ALabel.width:=sw-12;
            ALabel.Transparent:=false;
            ALabel.color:=clSilver;
            ALabel.visible:=true;
            ALabel.Caption:=n_lbl;
            ALabel.Parent := GroupBox1;
            ALabel.OnClick:=PanelClick;
            Inc(j);
         end;
      end;
      Inc(i);
   end;
MfG
Kurt Wallander

Der schöne Günther 7. Mär 2022 18:02

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Du gönnst dir ja nur eine Variable
Delphi-Quellcode:
ALabel
und packst da das grade zuletzt erstellte rein. Du musst dir das schon dauerhaft merken (z.B. in einem Array, Dictionary oder was auch immer).

Du wirst bestimmt auch Vorschläge bekommen, das Label später anhand der
Delphi-Quellcode:
Caption
wiederzufinden, aber das ist mMn der falsche Weg.

runningsoft 7. Mär 2022 19:03

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Ich iteriere in einem solchen Fall immer durch alle Compontenten des Parents. je nach Situation spreche ich die Komponeten dann über ihren Namen an oder einen vergebenen Tag. In etwa so:

Delphi-Quellcode:
var Temp: TComponent

...
for I := 0 to ScrollBox1.ComponentCount - 1 do
   begin
   Temp := ScrollBox1.Components[I];
   if Temp is TLabel then
    begin
    if TLabel(Temp).Name = 'blablub123' then
      begin
      //Machwas
      end;
    end;
   end;

Medium 7. Mär 2022 22:07

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Zitat:

Zitat von runningsoft (Beitrag 1503020)
Ich iteriere in einem solchen Fall immer durch alle Compontenten des Parents. je nach Situation spreche ich die Komponeten dann über ihren Namen an oder einen vergebenen Tag. In etwa so:

Alternativ könntest du auch ein paar Do-Nothing-Loops einbauen; verschwendet auch unnötig CPU Zyklen, ist aber wartbarer!

runningsoft 7. Mär 2022 22:29

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Zitat:

Zitat von Medium (Beitrag 1503022)
Zitat:

Zitat von runningsoft (Beitrag 1503020)
Ich iteriere in einem solchen Fall immer durch alle Compontenten des Parents. je nach Situation spreche ich die Komponeten dann über ihren Namen an oder einen vergebenen Tag. In etwa so:

Alternativ könntest du auch ein paar Do-Nothing-Loops einbauen; verschwendet auch unnötig CPU Zyklen, ist aber wartbarer!

Dann wäre ein konstruktiver Vorschlag für den TE vielleicht hilfreich?

Medium 7. Mär 2022 22:35

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Ich könnte nur Günther's Beitrag wiederholen, da war schon alles richtig. Im Übrigen finde ich es durchaus konstruktiv, bad practices zu kritisieren.

KodeZwerg 7. Mär 2022 23:01

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1503018)
Du gönnst dir ja nur eine Variable
Delphi-Quellcode:
ALabel
und packst da das grade zuletzt erstellte rein. Du musst dir das schon dauerhaft merken (z.B. in einem Array, Dictionary oder was auch immer).

Da das mit der Caption bereits geklärt ist hier ein Vorschlag zum erstellen der labels (nur hier per editor getippst...)
Delphi-Quellcode:
procedure LabelsDing(const ATarget: TGroupBox; const ALabels: Array of String);
var
  LblArr: Array of TLabel;
  Counter: Integer;
begin
  SetLength(LblArr, Pred(Length(ALabels)));
  for Counter := Low(ALabels) to High(ALabels) do
    begin
      LblArr[Counter] := TLabel.Create(ATarget);
      LblArr[Counter].Parent := ATarget;
      LblArr[Counter].Caption := ALabels[Counter];
      LblArr[Counter].Align := alTop;
      LblArr[Counter].Alignment := taCenter;
Auf diese Weise werden nur soviel Labels erstellt wie du strings übermittelst und alles wäre innerhalb des arrays ansprechbar.

jziersch 8. Mär 2022 06:25

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Zitat:

Zitat von KodeZwerg (Beitrag 1503026)
LblArr: Array of TLabel;

So ähnlich mache ich das immer. Allerdings müsste LblArr eine variable des Forms sein, am besten eine TList<Label>.

Man kann die Labels dann bei bedarf auch leicht zusätzliche Labels anfügen und sie jederzeit finden.
Parent sollte man allerdings zuletzt zuweisen und ATarget Begin/EndUpdate verwenden.

freimatz 8. Mär 2022 08:44

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Ich schlage Array[1..9,1..9] of TLabel vor.

@KodeZwerg:
a) LblArr[Counter] nicht merhfach verwenden. Besser noch eine einfache lokale Variable, die zuerst benutzen und dann am Ende ins Array umfüllen.
b) Eigenschaft Parent besser erst am Ende zuweisen.

Blup 8. Mär 2022 08:51

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
- Label.ParentColor := False // = eigene Farbe verwenden
- Konstanten machen den Code verständlicher und wartbarer
- For-Schleifen sind für eine vorher bekannte Anzahl von Durchläufen besser geeignet
- Koordinaten werden normalerweise mit x, y, ... bezeichnet
- Variablen sollten nicht mit A.. beginnen, das ist eigentlich Parametern vorbehalten (ALabel)
Delphi-Quellcode:
{Konstanten die an mehreren Stellen berücksichtigt werden}
const
  xmin = 1;
  xmax = 9;
  ymin = 1;
  ymax = 9;

type
  TForm1 = class(TForm)
{...}
    procedure PanelClick(Sender: TObject);
  private
    FMyIntegerArr: array[xMin..xMax, yMin..yMax] of Integer;
    FMyLabelArr: array[xMin..xMax, yMin..yMax] of TLabel;
    procedure InitMyLabel;
    function GetMyLabelPos(ALabel: TLabel): TPoint;
  end;

implementation

procedure TForm1.InitMyLabel;
var
  x, y: Integer;
  L: TLabel;
begin
  for y := ymin to ymax do
  begin
    for x := xmin to xmax do
    begin
      L := TLabel.Create(Self);
      L.Left := left_M - 5 + (x - xmin) * sw;
      L.Top := top_m - 5 + (y - ymin) * sw;
      L.Width := sw - 12;
      L.Height := sw - 12;
      L.Name := 'Feld' + IntToStr(y) + IntToStr(x);
      L.Caption := L.Name;
      l.ParentColor := False;
      L.Color := clSilver;
      L.Transparent := False;
      L.Parent := GroupBox1;
      L.OnClick := PanelClick;
      FMyLabelArr[x, y] := L;
    end;
  end;
end;

function TForm1.GetMyLabelPos(ALabel: TLabel): TPoint;
var
  x, y: Integer;
begin
  for y := ymin to ymax do
  begin
    for x := xmin to xmax do
    begin
      if FMyLabelArr[x, y] = ALabel then
      begin
        Result := TPoint(x, y);
        Exit;
      end;
    end;
  end;
  {nicht gefunden}
  Result := TPoint(-1, -1);
end;

procedure TForm1.PanelClick(Sender: TObject);
var
  P: TPoint;
  i: Integer;
begin
  P := GetMyLabelPos(Sender as TLabel);
  i := FMyIntegerArr[P.x, P.y];
  {...}
end;

dummzeuch 8. Mär 2022 08:55

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Es gibt immer die folgenden Möglichkeiten:
  1. Referenzen auf die Labels in einer wie immer gearteten Struktur (Array, Liste, Dictionary oder ggf. auch in einzelnen Variablen) zu speichern
  2. Label aus Controls[]-Property des Parents ermitteln, anhand des Namens (den man dann sinnvoll vergeben muss)
  3. Dito anhand ihrer Caption (problematisch, wenn z.B. Übersetzunen ins Spiel kommen)
  4. Dito anhand einer anderen Property, z.B. Tag

Ich persönlich verwende je nach Anwendung 1, 2 oder 4, mit starker Präferenz zu 1.

Statt Controls[] des Parents kann man auch Components[] des Owners nehmen. Kann evtl. sinnvoll sein, in der Regel ist es das aber nicht. Es ist auch wichtig, sicherzustellen, dass es in Controls[] nur diese Labels gibt, sonst hat man hinterher viel Spaß bei der Fehlersuche.

Kurt Wallander 8. Mär 2022 18:10

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Hallo Delphianer,
erst einmal vielen Dank für die Anregungen. Bin ein ganzes Stück vorangekommen. Die Anzeige der Daten klappt.
Ich bin dabei im wesentlichen den Tipps vor runningSoft gefolgt. Aber Überraschungen gab es doch noch. GroupBox1 als parent geht nicht, die generierten Labels haben trotzdem Form1 als owner. Dann mußte ich explizit die autosize-Methode auf false setzen, die Caption=name ist so klein, dass die wesentlich größere (Font.Size:=48) für die Daten nicht mehr zu sehen waren.
Ich benutze deshalb Labels, weil diese eine canvas haben und man aufwändige Schriftausgaben mit anderen Farben, Größen und Positionen bequem erzeugen kann. Man erinnere sich an das Aussehen eines Periodensystems aus dem Chemie-Unterricht.
Ich arbeite noch an dem onClick-Ereignis.
Nochmal vielen Dank an alle.
Kurt Wallander

bcvs 9. Mär 2022 06:53

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Zitat:

Zitat von Kurt Wallander (Beitrag 1503057)
GroupBox1 als parent geht nicht, die generierten Labels haben trotzdem Form1 als owner.

Parent <> Owner
Parent ist das Control, auf dem deine Labels liegen. Owner ist das Control, das sich um die Freigabe der Labels kümmert.

Delphi-Quellcode:
ALabel:=TLabel.Create(Self); // Hier wird der Owner gesetzt: Self, also das Form
ALabel.Parent := GroupBox1; // Hier wird der Parent gesetzt

Kurt Wallander 9. Mär 2022 07:56

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Hi,
aber trotzdem ist Groupbox1.componentcount=0, die erzeugten labels Feld11..Feld99 finde ich als Komponenten der Form1.

Kurt Wallander 9. Mär 2022 08:08

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Ich habe sowohl bei ALabel.create(GroupBox1) als auch ALabel.parent:=GroupBox1 stehen. Es funktioniert. Hatte Scheuklappen auf, da ich in anderen Programmen stets bei create stets self codiert hatte. Man lernt nicht aus!!!

Blup 9. Mär 2022 09:51

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Warum nimmst du dafür eigentlich kein Grid?
Insbesondere wenn du die einzelnen Zellen sowieso selbst zeichnen möchtest.
z.B. TDrawgrid

KodeZwerg 9. Mär 2022 12:23

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Oder eine TListView.

Zeige doch mal ein Bildschirmphoto von dem was Du da machst, da gibt es bestimmt viel mehr konstruktive Vorschläge.

Kurt Wallander 9. Mär 2022 20:27

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi Kodezwerg, hier ein screenshot. Es ist eine Sodoku-App. Die schwarzen Zahlen sind das Start-Bild, von einer Datei eingelesen. Das mintgrüne Feld wurde angeklickt und dient zur Eingabe der vom Nutzer erratenen Felder. Diese eingegebenen Zahlen sind von gleicher Größe, aber dann mit einer anderen Farbe. Sind Zeilen, Spalten oder Sub-Quadrate vollständig ausgefüllt, so werden diese mit Farbe unterlegt.
Beim onClick bin ich deinen Hinweisen weitgehendst gefolgt, auch dir meinen speziellen dank.
Kurt Wallander

TiGü 10. Mär 2022 07:31

AW: Ansprechen von während Laufzeit erzeugter Komponenten
 
Sodoku <> Sudoku!


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:47 Uhr.

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