Ich habe eine Frage zu Delphi:
Wenn ich mehreren Objekten zB. die gleiche Procedure auf das onclick - Ereignis zuweise, wie kann ich dann in der Procedure auf genau das Objekt zugreifen, das sie aufgerufen hat?
hans
Ich habe eine Frage zu Delphi:
Wenn ich mehreren Objekten zB. die gleiche Procedure auf das onclick - Ereignis zuweise, wie kann ich dann in der Procedure auf genau das Objekt zugreifen, das sie aufgerufen hat?
hans
Mach einen Parameter ‚Sender‘ vom Typ TObject.
Dann beispielsweise über den ClassName.
reHi,
das läuft über die variabele „Sender“, welche normalerweise übergeben wird. mit dem operator „As“ weist du dem „Sender“ eine klasse zu, damit delphi weiß, über welche methoden „Sender“ verfügt.
angenommen, du willst bei einem klick auf ein TEdit dessen text ändern. du hast allen "OnClick"s der TEdits die prozedur „DoMe“ zugewiesen:
procedure TForm1.DoMe (Sender: TObject);
begin
(Sender As TEdit).Text := ‚Neuer Text‘;
end;
ähnlich kannst du zB. das bild eines Speedbutton ändern:
procedure TForm1.DoMe (Sender: TObject);
begin
(Sender As TSpeedButton).Glyph := NeuesBild;
end;
via „IS“ kannst du die Klasse von „Sender“ püfen…
procedure TForm1.DoMe (Sender: TObject);
begin
if Sender Is TEdit then
(Sender AS TEdit).Text := ‚Neuer Text‘;
if Sender Is TSpeedbutton then
(Sender As TSpeedbutton).Glyph := NeuesBild;
end;
das ganze kann dann auch mit „With“ laufen…
with (Sender As TEdit) do begin
Text := ‚Neuer Text‘;
…
end;
zu guter letzt:
wenn du 20 labels auf eine prozedur gelegt hast, diese aber einzeln behandeln willst kannst du den Labelnamen verwenden:
procedure TForm1.DoMe (Sender: TObject);
var aLabel: TLabel;
begin
aLabel := (Sender As TLabel);
if aLabel.Name = ‚Label1‘ then …
…
end;
PS:
Ich habe mal eine reihe von reportlabels ansprechen müssen (automatische platzierung auf dem formular und so). dazu habe ich diese labels im namen nummeriert (la_XXX)…
danach brauchte ich nur den namen ermitteln, die ersten 3 zeichn löschen und den rest in einen integer umrechnen. damit stand mir ein indexwert für ein array zur verfügung in dem ich dann alle daten hinterlegt hatte…
die ganze formatiererei hatte sich damit in 10 zeilen source erledigt…
CU, DiJey
zu guter letzt:
wenn du 20 labels auf eine prozedur gelegt hast, diese aber
einzeln behandeln willst kannst du den Labelnamen verwenden:procedure TForm1.DoMe (Sender: TObject);
var aLabel: TLabel;
begin
aLabel := (Sender As TLabel);
if aLabel.Name = ‚Label1‘ then …
…
end;
Hi Dirk/DiJey,
mit der Verwendung des Labelnamens kommst Du sicher zum Ziel, es geht aber auch noch (eine Winzigkeit) besser. Für genau den beschriebenen Zweck ist nämlich das „Tag“-Property, über das jede Komponente verfügt, vorgesehen. Dabei handelt es sich um eine gewöhnliche INTEGER-Zahl, die Du im Objektinspektor oder zur Laufzeit beliebig setzen kannst. Wenn Du drei Labels hast, und deren Tag-Werte z. B. auf 1, 2 und 3 setzt, dann kannst Du schreiben:
CASE (Sender AS TButton).Tag OF
1: (TueDies);
2: (TueDas);
3: (TueSonstwas)
END
Die Vorteile sind, daß etwaige Änderungen am LabelNamen nicht weitere Änderungen irgendwo in den Tiefen des Quelltexts erfordern, und daß Du bei Arrays von Buttons nicht (mehr oder weniger umständlich) Zahlen aus den Namensstrings zu „extrahieren“ brauchst. Ferner sieht so eine ganze Reihe untereinanderstehender IF … THEN …-Konstrukte irgendwie wenig professionell aus. Und zu guter Letzt wird „CASE OF“ auch schneller abgearbeitet, aber dieser Vorteil dürfte zugegebenermaßen nur in den wenigsten Fällen von Bedeutung sein.
Mit delphianischem Gruß
Martin
Zu Martins Antwort:
die Eigenschaft „Tag“ haben alle alle Komponenten. Das heißt, du kannst z.B. OnClick-Ereignisse von Labels, Buttons, Speedbuttons, Panels usw. zusammenfassen und mit
case TComponent(Sender).Tag of
…
entsprechende Anweisungen aufrufen.
Die Typabfrage mit „is“ bzw. Typkonvertierung mit „as“ (Sender as TComponent) sind relativ langsam und sind nur zu verwenden, wenn du nicht sicher bist, was als Sender so alles in Frage kommt. „as“ löst eine Exception aus, wenn die Typen nicht übereinstimmen und ignoriert die weiteren Anweisungen. Eine Anweisung wie
if Sender is TButton then
(Sender as TButton).caption := …
else
…
ist viel zu langsam und umständlich. Besser ist
try
(Sender as TButton).caption := …
except
…
end
Am besten ist aber, wenn du weißt, daß es eine TButton-Klasse sein MUSS. Dann ist die direkte Typkonvertierung zu nutzen:
TButton(Sender).caption := …
Gruß
Jochen
reHi,
korrekt. ich war acu über case…of gegangen.
allerdings gefällt mir die tag-lösung nicht so gut weil man das tag sehr leicht übersieht…
aber das ist ansichtssache…
CU, DiJey