Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi dynamische Komponenten (https://www.delphipraxis.net/1770-dynamische-komponenten.html)

Privateer3000 22. Dez 2002 16:37


dynamische Komponenten
 
Wie kann ich ein Form dazubringen,
mir Label zur erstellen in der Anzahl die ich möchte,
aber so anordnet das es "ein Bild" gibt.D.h. wenn es zb: 12 sind
4x3 Spalten/Zeilen, wenn es 24 sind 4x6 ?
Hab sowas schon in PHP gemacht, aber hier keinen Plan :(

PS: Die Übergabe der Anzahl ist durch eine globale VAriable geregelt.

jbg 22. Dez 2002 17:24

Delphi-Quellcode:
for i := 0 to Anzahl - 1 do
begin
  Spalte := i mod 4;
  Zeile := i div 4;
  ErzeugeLabel({Left:}Spalte * 80, {Top:}Zeile * 25);
end;

Privateer3000 22. Dez 2002 18:09

kannst du mir bitte das erklären?
Nur das ich weiss was da passiert.

jbg 22. Dez 2002 18:18

Stelle dir vor du legtst mehrere Steine auf ein Brett. Den Ersten legst du ganz links oben hin, den Zweiten rechts daneben, den Dritten wiederum daneben und den Vierten ebenfalls. Den Fünften hingegen legst du unter den Ersten, ...

Um nun herauszubekommen, in welcher Zeile du den Stein hinlegen musst, ziehst du 1 von der Nummer ab (also Stein 1 ist Stein 0) und dividierst diesen Wert durch 4. Somit ergibt sich für die Steine mit Index 0-3 die Zeile mit Index 0 (0 div 4 = 0, 1 div 4 = 0, ... 3 div 4 = 0).
Der Stein mit Index 4 nun ist durch 4 Teilbar und ergibt somit die Zeile mit Index 1. ...
Um nun aber noch die richtige Spalte herauszubekommen benötigen wir den Restwert der Division (mod). So ergibt 0 mod 4=0, 1 mod 4=1, 2 mod 4=2, 3 mod 4=3. Und für den Stein mit dem Index 4 ergibt dann 4 mod 4=0, womit die Spaltenzählung von vorne beginnt.

Privateer3000 22. Dez 2002 22:43

Danke für die Ausführung.
Ich habe folgenden Test gemacht:
Code:
procedure TForm1.FormShow(Sender: TObject);
var
i,Spalte,Zeile:integer;
aLabel: TLabel;
begin
for i := 0 to 24 - 1 do
begin
  Spalte := i mod 4;
  Zeile := i div 4;
  aLabel:=TLabel.Create(Self);
  aLabel.Left:=Spalte*80;
  aLabel.Top:=Zeile*25;
  aLabel.Caption:='Label'+IntToStr(i);
end;
end;
es startet auch,keine Fehlermeldung, aber es werden keine Labels,gezeichnet.
was ist falsch?

nailor 22. Dez 2002 23:04

wenn mich nicht alles täuscht ist der kram standardmäßig auf invisible gestellt...

Privateer3000 22. Dez 2002 23:12

bei create?
denn normalerweise eher nicht.

Privateer3000 22. Dez 2002 23:21

witzig! das Form heisst wie das letzte Label:Nämlich Label23.
Und wenn ich noch Height und Width übergebe ist das Form in diese Grösse.
dabei sage ich doch das aLabel ein TLabel ist......

jbg 22. Dez 2002 23:27

Ich reiche dir mal ein
Delphi-Quellcode:
aLabel.Parent := Self;

Privateer3000 22. Dez 2002 23:39

kaum zu glauben..in der Tat jetzt gehts.
Also muss ich den Labels sagen zu wem sie gehören?!

Danke

jbg 22. Dez 2002 23:47

Ja, du musst jeder Komponente sagen, wer für das Freigeben zuständig ist (Owner) und wer für das Anzeigen (Parent).

Privateer3000 23. Dez 2002 06:23

Ich hab noch einen :mrgreen:
wie sage ich dem ersten LAbel an welche Position es muss.
Denn es wird ganz links oben mit dem Aufbau der Labels begonnen.
Bisher konnt ich immer alles auf IDE positionieren.Aber mit Komps die erst zur Laufzeit erstellt hantiere ich zum erstenmal.

Einen schönen Montag

jbg 23. Dez 2002 08:24

Verschieben kannst du das ganze, indem du bei der Zuweisung an Left unt Top noch einen (konstanten) Wert hinzufügst:
Delphi-Quellcode:
aLabel.Left := StartX + Spalte*80;
  aLabel.Top := StartY + Zeile*25;

Christian Seehase 23. Dez 2002 13:11

Moin Zusammen,

Zitat:

Zitat von jbg
du musst jeder Komponente sagen, wer für das Freigeben zuständig ist (Owner) und wer für das Anzeigen (Parent).

Nur der Vollständigkeit halber:
Bei dynamisch erzeugten TTabSheet, muss man auch noch das zugehörige PageControl angeben, damit man von den Tabsheets was sieht.

Privateer3000 23. Dez 2002 14:30

Habt vielen Dank,
jetzt klappt es so wie ich es wollte.Und verstanden hab ich es auch :angle2: , hoffe ich jedenfalls.
Wie spricht man im laufenden Programm so eine erstellte Komponente an?
Wie eine "normale" auch?Denn sie sollen ja im Programm auch weiterbehandelt, bzw angesprochen werden.

Ich glaub das war jetzt ne blöde Frage,egal :o)

jbg 23. Dez 2002 14:36

Entweder du legst ein Array[0..24-1] of TLabel an, oder du verpasst jedem Label auch einen Namen, den du dann mit Owner.FindComponent wieder finden kannst.

Christian Seehase 23. Dez 2002 14:51

Moin Privateer,

Du hast doch in dem einen Beispiel eine Variable aLabel vom Typ TLabel.
aLabel muss nur an einer Stelle im Programm deklariert werden, so dass Du von jeder Stelle an der Du sie brauchst auch da rankommst.

Wird sie z.B. nur innerhalb von Methode von Form1 gebraucht, kannst Du dort im Abschnitt private die Variable unterbringen.

Delphi-Quellcode:
TForm1 = class(TForm)
...
private
  FaLabel : TLabel;
...
end;

var
  Form1 : TForm1;
Das führende F muss nicht sein, damit wird nur den Namenskonventionen für Felder (Variablen) von Objekten/Klassen genüge getan.

jbg 23. Dez 2002 14:59

Das Problem dabei ist aber, dass die Variable aLabel eben nicht alle 24 Labels gleichzeitig referenzieren kann. Somit wird er um ein Array bzw. die Name-Lösung nicht herumkommen.

Privateer3000 23. Dez 2002 15:02

wie soll das funktionieren mit dem array?
Die Anzahl der Labels ist ja variabel.

*schnüff*

jbg 23. Dez 2002 15:11

Schon mal was von einem dynamischen Array gehört?

Delphi-Quellcode:
SetLength(LabelArray, AnzahlDerLabels);

Privateer3000 23. Dez 2002 15:16

nein :oops:

nailor 23. Dez 2002 15:54

probier mal das zu verstehen, und eventuell anzupassen:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure LabelClick(Sender: Tobject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  DeineLabel: array of TLabel;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var i : Integer;
begin
i := succ(High(DeineLabel));
SetLength(DeineLabel,i + 1);                //Der array mit deinen Labeln wird eins länger
DeineLabel[i] := TLabel.Create(Form1);      //In den grade erschaffenen Platz kommt ein Label
DeineLabel[i].Left := 10;                   //Wohin
DeineLabel[i].Top := i * 20;               //Wohin
DeineLabel[i].Color := clred;               //Farbe
DeineLabel[i].OnClick := LabelClick;        //Was ist, wenn man klickt
insertcontrol(DeineLabel[i]);               //Label "wirklich" erstellen
end;

procedure TForm1.LabelClick(Sender: TObject);
begin
if Sender = DeineLabel[0] {irgendeine Zahl statt 0} then
  {was bei dem Label passieren soll} Form1.Close;
end;

end.

jbg 23. Dez 2002 18:23

Und noch eine kurze Erklärung zu
Zitat:

insertcontrol(DeineLabel[i]);
Diese Zeile entspricht dieser:
Delphi-Quellcode:
DeineLabel[i].Parent := Self;

Privateer3000 23. Dez 2002 22:09

@Nailor

in deinem Beispiel,ich blick offengesagt noch nicht ganz durch.
Wieviele Labels werden in diesem Beispiel denn erstellt.Das kann ich darin nicht sehen.Oder ist dein arraynur angedeudet?

jbg 23. Dez 2002 22:11

Bei Nailors Beispiel werden so viele Labels erzeugt wie du auf den Button Button1 klickst.

nailor 23. Dez 2002 22:46

jbg meint, dass jedesMal, wenn man auf den Button klickt, ein neues Label entsteht. Du kannst auch den Code 1:1 ausschneiden, bei Delphi ein neues Projekt starten, einen einzigen Button einfügen und das Programm starten. Dann kannst du sehen, was es macht.
Dann kannst du ein paar Werte ändern, und per Trial and Error dir ein paar Auswirkungen klar machen.

Privateer3000 24. Dez 2002 06:25

gehts das nicht einfacher?
Jedem Label einfach einen Namen verpassen wie
einen Startwert festlegen dann jeweils um 1 hochzählen?

Christian Seehase 24. Dez 2002 10:18

Moin Privateer,

wenn Du den Labeln beim Erzeugen keinen Namen zuweist, wird der Standardname erzeugt, also eben Label1, Label2 usw., nur lassen sie sich über ein Array of TLabel leichter ansprechen.
Sonst müsstest Du sie immer mit FindComponent suchen.

Privateer3000 24. Dez 2002 15:47

Hi Chris,

das werden sie sowieso in jedem Fall.Jedenfalls in diesem Programm.
Beispiel:
Code:
procedure TForm1.AnyInChange(Sender: TObject);
var
  bEdit: TEdit;
  cLabel: TLabel;
  begin
  if Sender <> nil then
    if Sender is TEdit then
    begin
      bEdit := FindComponent('in' + Copy(TEdit(Sender).Name, 3, 2)) as TEdit;
      cLabel := Form2.FindComponent('out' + Copy(TEdit(Sender).Name,3,2)) as TLabel;
      cLabel.Caption:=bEdit.Text;
      end;
      end;
So und so ähnlich werden sie im kompletten Programm angesprochen.Deswegen meine Vermutung ob es nicht einfacher ginge.
Ich konnte es nur nicht nachvollziehen, ob jedes Label den richtigen Namen bekommt, weil es man nicht sieht.
Denn alles "Findcomponents" sind auf eine bestimmte Zahl abgestimmt.Will sagen egal wie die Komponenten heissen haben sie die gleich Zahl, die die ich ansprechen will.

Einen geruhsamen heiligen Abend an alle!
(Werd noch a bisserl rumprobieren :o) )

Christian Seehase 24. Dez 2002 16:30

Moin Privateer,

nimm doch lieber die Array Variante.
Das dürfe deutlich einfacher gehen.

Privateer3000 24. Dez 2002 17:11

nun stehen aber schon alle proceduren auf findcomponents.dann muss ich ja alles wieder umschmeissen.
Wenn ich das richtig verstanden haben, kann ich trotzdem so erzeugen:
Code:
var
i,Spalte,Zeile:integer;
aLabel: TLabel;
begin
for i := 0 to 25 - 1 do
begin
  Spalte := i mod 4;
  Zeile := i div 4;
  aLabel.Parent:=Self;
  aLabel:=TLabel.Create(Self);
  aLabel.Left:=50+Spalte*80;
  aLabel.Top:=50+Zeile*25;
  aLabel.Caption:='Label'+IntToStr(i);
end;
end;
und mit findcomponents ansprechen?!

Christian Seehase 24. Dez 2002 17:14

Moin Privateer,

ja, das sollte gehen.

Privateer3000 24. Dez 2002 17:20

ich habe boch einen Christian.. :mrgreen:
Ist es prinzipell möglich solchen Komps zu sagen wie gross sie sein sollen?
Ich meine wenn das Array bis 24 geht, sollen die Labels kleiner sein, als wenn nur 12 angezeigt werden.
(Gleich ist es soweit...und ich fliege aus'm Board)

Privateer3000 24. Dez 2002 18:42

sorry, falls das falsch ankam mit dem rausfliegen..
war etwas ironisches zu mir selbst

Christian Seehase 27. Dez 2002 03:49

Moin Privateer,

wenn Du die Eigenschaft AutoSize der Label auf false setzt, kannst Du problemlos die Eigenschaften Width und Height verwenden, um die Grösse Deinen Wünschen anzupassen.
(falls es das war, was Du wissen wolltest;-))

Privateer3000 27. Dez 2002 06:30

So weit, so gut.Bleibt für mich die Frage wie sag ich's ihnen, den Labels.
Code:
if Anzahl >=12 then
      begin
      aLabel.Width:=100;
      aLabel.Height:=60;
      end
      else
      ....
oder so ähnlich?
Geht das nich auch unter Prozentualen Angaben??

?Ist es eigentlich möglich Komponenten eine gewisse Transparenz zu geben?


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:45 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-2025 by Thomas Breitkreuz