Autor |
Beitrag |
roka6803
      
Beiträge: 50
Delphi 5 Ent. & Delphi 7
|
Verfasst: Mi 14.09.05 14:30
Hallo alle zusammen,
ich habe ein Problem mit dem dynamischen erzeugen von 6 Labels.
Bemerkung: Der von mir gezeigte Quelltext ist gekürzt und enthält an der "fraglichen Stelle" lediglich Quelltext für das erzeugen von EINEM Label.
Ich habe vor diesen "fraglichen Teil" in eine weitere von der ersten nur durch ein boolschen Wert abhängige For-Do-Schleife zu packen, sodass auch die Captions der Labels sowie die zugehören OnKlick-Ereignisse variabel sein können (captions kommen dann aus einem array und die prozeduren für die onclick ereignisse werden durchnummeriert sein).
Ein besonderes Problem stellt bei mir die Stelle
Delphi-Quelltext 1:
| OnClick := menu_label_click; |
dar, weil mir dort immer Fehler angezeigt werden !
Bemerkung 2 : Es reicht mir wenn hier die Lösung zustande kommt nur ein Label dyn. zu erzeugen, aber wie gesagt unter der beachtung der "weiteren *pas" !
Jetzt meine Frage(n): Wie kann ich den Teil zum Erzeugen der sechs Label in eine weitere *.pas packen, welche dann auch die OnClick-Ereignis-Prozeduren enthält? Wie muss ich dann diese in der ersten unit deklarieren ?
Wie muss in dem "fraglichen Teil" die Zuweisung Onlick := menu_label_click; richtig aussehen, damit sie funzt ?
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68:
| unit ...;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, jpeg, ExtCtrls;
type Tform_loading_screen = class(TForm) ....... private public end;
var ...... menu_label : TLabel;
implementation
....
procedure Tform_loading_screen.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var i,n : integer; begin
if loading_boolean = true then begin n := 10; loading_status[1] := ........
for i := 0 to n - 1 do begin loading_status_count := i+1; Label2.Caption := (loading_status[loading_status_count]); label2.Refresh; sleep(400); loading_progress.StepIt; sleep(400); end;
loading_boolean := false;
menu_label := TLabel.Create(Self); with menu_label do begin Parent:=form_loading_screen; Caption:='Beschriftung'; Transparent := true; font.size := 11; font.color := clWhite; Left:=100; Top:=100; OnClick := menu_label_click; end;
end; end;
end. |
_________________ Signatur? Was ist das? Brauch ich nicht...
|
|
ManuelGS
      
Beiträge: 173
Win XP HE, Suse Linux
D6, D7, D2005 Personal
|
Verfasst: Mi 14.09.05 14:42
Wo ist die Deklaration von menu_label_click?
_________________ "Leben ist gänzlich Bühne und Spiel; so lerne denn spielen
und entsage dem Ernst - oder erdulde das Leid." - Palladas von Alexandria
|
|
roka6803 
      
Beiträge: 50
Delphi 5 Ent. & Delphi 7
|
Verfasst: Mi 14.09.05 14:52
ManuelGS hat folgendes geschrieben: | Wo ist die Deklaration von menu_label_click? |
Genau diese On-Click-Ereignis-Prozedur soll komplett in einer anderen Unit stehen.
In der ersten Unit soll sozusagen nur die erzeugende Prozedur stehen, die dann für das OnCklick-Ereignis des neu entstandenen Labels auf die zweite Unit "verweist" !
_________________ Signatur? Was ist das? Brauch ich nicht...
|
|
Grishnak
      
Beiträge: 221
Windows XP Home
Delphi 7 PE, Delphi 2005 PE
|
Verfasst: Mi 14.09.05 14:56
Du musst dem OnClick-Property eines TLabel-Objektes ein TNotifyEvent zuweisen. Dies hat folgende Form
Delphi-Quelltext 1:
| type TNotifyEvent = procedure (Sender: TObject) of object; |
D.h. dein menu_label_click muss ebenfalls diese Form haben!
_________________ Mach' etwas idiotensicher und irgendjemand erfindet einen besseren Idioten!
|
|
ManuelGS
      
Beiträge: 173
Win XP HE, Suse Linux
D6, D7, D2005 Personal
|
Verfasst: Mi 14.09.05 15:01
Du könntest eine zweite Unit schreiben, die die gewünschte Prozedur enthält, und dann mittels {$i dateiname.pas} (ich hoffe, ich irre mich nicht) inkludieren.
Oder aber du bindest sie "normal" bei der Uses-Klausel ein.
_________________ "Leben ist gänzlich Bühne und Spiel; so lerne denn spielen
und entsage dem Ernst - oder erdulde das Leid." - Palladas von Alexandria
|
|
roka6803 
      
Beiträge: 50
Delphi 5 Ent. & Delphi 7
|
Verfasst: Mi 14.09.05 15:08
IN welche Uses-Klausel ? Der vor, oder der nach "Implementation" ?
Und: Wie genau und wo genau muss das mit dem "NotifyEvent" hin ?
_________________ Signatur? Was ist das? Brauch ich nicht...
|
|
ManuelGS
      
Beiträge: 173
Win XP HE, Suse Linux
D6, D7, D2005 Personal
|
Verfasst: Mi 14.09.05 15:24
In diesem Fall würd es im Implementation-Teil ausreichen.
Wenn's nicht klappen sollte, dann halt in den Interface-Teil.
_________________ "Leben ist gänzlich Bühne und Spiel; so lerne denn spielen
und entsage dem Ernst - oder erdulde das Leid." - Palladas von Alexandria
|
|
Grishnak
      
Beiträge: 221
Windows XP Home
Delphi 7 PE, Delphi 2005 PE
|
Verfasst: Mi 14.09.05 15:26
Unit, die die Prozedur enthält:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| unit Egal;
interface
[...]
procedure menu_label_click(Sender: TObject);
implementation
[...]
procedure menu_label_click(Sender: TObject); begin [...] end; |
Unit, die die Form mit dem/den Label(s) enthält:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| unit MitLabel;
[...]
implementation
uses Egal[...];
[...]
MeinLabel.OnClick:=menu_label_click; |
So müsste es funktionieren!
_________________ Mach' etwas idiotensicher und irgendjemand erfindet einen besseren Idioten!
|
|
roka6803 
      
Beiträge: 50
Delphi 5 Ent. & Delphi 7
|
Verfasst: Mi 14.09.05 15:37
Also ich würde das jetzt so schreiben:
Unit 1:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| ...
menu_label := TLabel.Create(Self); with menu_label do begin Parent:=form_loading_screen; Caption:='Beschriftung'; Transparent := true; font.size := 11; font.color := clWhite; Left:=100; Top:=100; menu_label.OnClick := menu_label_click; end;
...
end. |
Und Unit 2 wie vorher beschrieben.
OK, werds mal probieren !
_________________ Signatur? Was ist das? Brauch ich nicht...
|
|
roka6803 
      
Beiträge: 50
Delphi 5 Ent. & Delphi 7
|
Verfasst: Mi 14.09.05 15:45
OK, habe es ausprobiert. Eigentlich funzt alles, doch bei menu_label.OnClick := menu_label_click; haut der den Fehler "[Error] loading_screen.pas(95): Incompatible types: method pointer and regular procedure" rein.
Ansonsten hab ich alles so gemacht wie ihr vorgeschlagen habt !
_________________ Signatur? Was ist das? Brauch ich nicht...
|
|
Grishnak
      
Beiträge: 221
Windows XP Home
Delphi 7 PE, Delphi 2005 PE
|
Verfasst: Mi 14.09.05 15:53
mhhh. Stimmt! Das klappt so leider nicht!
EDIT: Man kann der OnClick-Property nur Objekt-Methoden zuweisen! Du kannst aber in der Form ein OnClick-Ereignis-Prozedur für dein(e) Label(s) schreiben, in der du dann menu_label_click aufrufst:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
| [...]
type Tform_loading_screen = class(TForm) ....... procedure LabelOnClick(Sender: TObject); private public end;
[...]
with menu_label do begin Parent:=form_loading_screen; Caption:='Beschriftung'; Transparent := true; font.size := 11; font.color := clWhite; Left:=100; Top:=100; menu_label.OnClick := form_loading_screen.LabelOnClick; end;
[...]
procedure Tform_loading_screen.LabelOnClick(Sender: TObject); begin menu_label_click; end;
[...] |
_________________ Mach' etwas idiotensicher und irgendjemand erfindet einen besseren Idioten!
Zuletzt bearbeitet von Grishnak am Mi 14.09.05 16:06, insgesamt 1-mal bearbeitet
|
|
Amateur
      
Beiträge: 777
(Win98, WinMe) WinXP Prof
D3 Prof, D6 Pers, D2k5 Pers., Turbo C++ Explorer
|
Verfasst: Mi 14.09.05 16:02
hatte ich auch schon. versuch ma sender:tobject als variable zusätzlich zu deiner eignene procedure zu schreiben. also bei deiner procedure: procedure meineprocedure (sender:tobject);
ich habs net getestet aber das liegt auf jeden fall an den parametern von onclick und deiner procedure. ansonsten ma alle parameter von ner onclick procedure bei deiner eigene procedure übergeben. hat bei mir hingehauen. sollte aber mit sender reichen
_________________ "Kein dummes Gerede. Kein Rumrätseln. Denkt an nichts anderes mehr, nur noch an das, was vor euch liegt. Das ist die wahre Herausforderung. Ihr müßt euch vor euch selbst schützen, Leute." (Rennes in "Cube")
Beiträge: >700
|
|
roka6803 
      
Beiträge: 50
Delphi 5 Ent. & Delphi 7
|
Verfasst: Mi 14.09.05 16:04
Grishnak hat folgendes geschrieben: | mhhh. Stimmt! Das klappt so leider nicht!  |
Wie könnte man das mit dem Notify Event machen ?
_________________ Signatur? Was ist das? Brauch ich nicht...
|
|
roka6803 
      
Beiträge: 50
Delphi 5 Ent. & Delphi 7
|
Verfasst: Mi 14.09.05 16:07
Amateur hat folgendes geschrieben: | hatte ich auch schon. versuch ma sender:tobject als variable zusätzlich zu deiner eignene procedure zu schreiben. also bei deiner procedure: procedure meineprocedure (sender:tobject);
ich habs net getestet aber das liegt auf jeden fall an den parametern von onclick und deiner procedure. ansonsten ma alle parameter von ner onclick procedure bei deiner eigene procedure übergeben. hat bei mir hingehauen. sollte aber mit sender reichen |
geht auch nicht dann haut er noch mehr fehler raus wie "expected dass statt dem und expected dort weil da hier und son kram..."
_________________ Signatur? Was ist das? Brauch ich nicht...
|
|
ManuelGS
      
Beiträge: 173
Win XP HE, Suse Linux
D6, D7, D2005 Personal
|
Verfasst: Mi 14.09.05 17:21
Ist zwar ein hässliches Stück Code, aber reicht wohl zu Demonstrationszwecken.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| unit Unit2;
interface
uses dialogs,stdctrls,classes,unit1;
procedure machdielabelsdrauf;
implementation
procedure klick(sender:tobject); begin showmessage('Eo Captain Jack, Heureka und Quantensprung - es klappt.'); end;
procedure machdielabelsdrauf; var lab:tlabel; ereignisprozedur:tnotifyevent; begin lab:=tlabel.create(form1); lab.Parent:=form1; lab.Caption:='GUTEN TAG - BITTE KLICKEN SIE MICH AN'; @ereignisprozedur:=@klick; lab.onclick:=ereignisprozedur; end;
end. |
In der anderen Unit diese hier im Implementation-Teil einbinden; per Button etc. dann "Machdielabelsdrauf" aufrufen.
_________________ "Leben ist gänzlich Bühne und Spiel; so lerne denn spielen
und entsage dem Ernst - oder erdulde das Leid." - Palladas von Alexandria
|
|
Amateur
      
Beiträge: 777
(Win98, WinMe) WinXP Prof
D3 Prof, D6 Pers, D2k5 Pers., Turbo C++ Explorer
|
Verfasst: Mi 14.09.05 17:29
du musst deine procedure ner klasse zuweisen. wenn ich ne procedure als methode von tform1 schreibe kann ich sie so wie du es willst zuweisen. musste ma probieren. jednefalls muss es ne methode ner klasse sein. ganz ohne was gehts wohl net.
könntest also ne klasse machen tmeineklasse und der die procedure zuweisen und dann machste label1.onclick:=meineklasse.click;
wirst auch noch den sender als parameter geben müssen bin aber net sicher
ok das von manuel sollte auch gehn. is sogar noch besser
_________________ "Kein dummes Gerede. Kein Rumrätseln. Denkt an nichts anderes mehr, nur noch an das, was vor euch liegt. Das ist die wahre Herausforderung. Ihr müßt euch vor euch selbst schützen, Leute." (Rennes in "Cube")
Beiträge: >700
|
|
roka6803 
      
Beiträge: 50
Delphi 5 Ent. & Delphi 7
|
Verfasst: Mi 14.09.05 18:27
OK, es klappt alles wunderbar.
Ich habe es jetzt so weit, dass dank einer For-Do-Schleife fünf Label erzeugt weren. Alle mit einer anderen Caption.
Jetzt würde ich es gerne so einrichten, dass jedes Label noch eine eigene OnClick-Prozedur besitzt.
Hier mein aktueller (gekürzter) Quelltext:
Unit 1
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58:
| unit loading_screen;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, jpeg, ExtCtrls;
type Tform_loading_screen = class(TForm) ... private public end;
var ...
implementation
uses loading_screen_menu_labels; {$R *.DFM}
procedure Tform_loading_screen.FormCreate(Sender: TObject); begin ... end;
procedure Tform_loading_screen.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var i,n : integer; begin if loading_boolean = true then begin n := 10; loading_status[1] := ...
for i := 0 to n - 1 do begin loading_status_count := i+1; Label2.Caption := (loading_status[loading_status_count]); label2.Refresh; sleep(400); loading_progress.StepIt; sleep(400); end;
loading_boolean := false;
menu_label_erzeugen; end; end;
end. |
Unit 2
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
| unit loading_screen_menu_labels;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, jpeg, ExtCtrls;
procedure menu_label_erzeugen;
var menu_label_caption : Array [1..5] of String;
implementation
uses loading_screen; procedure klick(sender:tobject); begin showmessage('Eo Captain Jack, Heureka und Quantensprung - es klappt.'); end;
procedure menu_label_erzeugen; var menu_label : tlabel; ereignisprozedur : tnotifyevent; i,e : integer;
begin
menu_label_caption[1] := ...
e := 100;
for i := 0 to 4 do begin menu_label := tlabel.create (form_loading_screen); menu_label.Parent := form_loading_screen; menu_label.Caption := menu_label_caption[i+1]; menu_label.Top := e; inc(e,20); menu_label.Left := 100; menu_label.Transparent := true; menu_label.Font.Size := 11; menu_label.Font.Color := clRed; @ereignisprozedur := @klick; menu_label.onclick := ereignisprozedur; end; end;
end. |
Wie kann jetzt jedes Label seine eigene OnKlick-Prozedur bekommen ?
MfG roka6803
PS Was hat das mit dem @ereignisprozedur := @klick; zu bedeute ? Ich weiss nur, dass es ohne nicht geht !
_________________ Signatur? Was ist das? Brauch ich nicht...
|
|
Grishnak
      
Beiträge: 221
Windows XP Home
Delphi 7 PE, Delphi 2005 PE
|
Verfasst: Mi 14.09.05 18:39
_________________ Mach' etwas idiotensicher und irgendjemand erfindet einen besseren Idioten!
|
|
roka6803 
      
Beiträge: 50
Delphi 5 Ent. & Delphi 7
|
Verfasst: Mi 14.09.05 18:45
Danke, Grishnak !
Dieses NotifyEvent, würde das auch mit OnMouseOver statt OnClick funzen ?
MfG roka6803
Edit:
Es hat sich ein neues Problem ergeben: Das mit dem Noti...Array funzt wunderbar nur in der Zeile @ereignisprozedur := @klick bekomme ich ne Fehlerausgabe !
Ansonsten keine weiteren Fehler.
Hier mein (diesmal ungekürzt) Quelltext von Unit2 (der aus Unit1 ist noch wie in meinem vorigen Post):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81:
| unit loading_screen_menu_labels;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, jpeg, ExtCtrls;
procedure menu_label_erzeugen;
var menu_label_caption : Array [1..5] of String; ereignisprozedur : Array [0..4] of TNotifyEvent;
implementation
uses loading_screen;
procedure klick_newgame(sender:tobject); begin showmessage('Neues Spiel starten...'); end;
procedure klick_loadgame(sender:tobject); begin showmessage('Gespeichertes (lokales) Spiel laden...'); end;
procedure klick_options(sender:tobject); begin showmessage('Optionen öffnen...'); end;
procedure klick_credits(sender:tobject); begin showmessage('Credits : Na wer hat das denn gemacht ?'); end;
procedure klick_close(sender:tobject); begin Application.Terminate; end;
procedure menu_label_erzeugen; var menu_label : tlabel; i,e : integer;
begin
menu_label_caption[1] := 'Neues Spiel'; menu_label_caption[2] := 'Spiel laden'; menu_label_caption[3] := 'Optionen'; menu_label_caption[4] := 'Credits'; menu_label_caption[5] := 'Beenden';
@ereignisprozedur[0] := @klick_newgame; @ereignisprozedur[1] := @klick_loadgame; @ereignisprozedur[2] := @klick_options; @ereignisprozedur[3] := @klick_credits; @ereignisprozedur[4] := @klick_close;
e := 100;
for i := 0 to 4 do begin menu_label := tlabel.create (form_loading_screen); menu_label.Parent := form_loading_screen; menu_label.Caption := menu_label_caption[i+1]; menu_label.Top := e; inc(e,20); menu_label.Left := 100; menu_label.Transparent := true; menu_label.Font.Size := 11; menu_label.Font.Color := clRed; @ereignisprozedur[i] := @klick[i]; menu_label[i].onclick := ereignisprozedur[i]; end; end;
end. |
_________________ Signatur? Was ist das? Brauch ich nicht...
Zuletzt bearbeitet von roka6803 am Mi 14.09.05 19:07, insgesamt 1-mal bearbeitet
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mi 14.09.05 18:47
Grishnak hat folgendes geschrieben: | Delphi-Quelltext 1:
| @ereignisprozedur := @klick; |
ereignisprozedur ist im var-Block als TNotifyEvent deklariert. Mittels dieser Zuweisung lässt du sie auf die klick-Prozedur zeigen. Das ist zwar sehr schmutzig programmiert, aber es klappt! |
Normalerweise ist das Zuweisen von Evenst nicht schmutzig, sondern eigentlich eine Standardvorgehensweise. In diesem Fall wundert es mich, dass das überhaupt funktioniert.
Denn, wie Du selber geschrieben hast, ist ein TNotifyEvent eine Methode, also eine procedure of object. "Klick" ist jedoch eine einfache Prozedur. Ich denke, dass man deswegen die Klimmzüge mit @.. := @.. machen muss, im Normalfall weist man die Methode einfach zu und fertig.
Ich denke, man fängt sich durch dieses "Zuweisen mit der Brechstange" eine potentielle Fehlerquelle ein, da eine Methode noch einen versteckten Parameter "self" besitzt, den eine Prozedur nicht hat. Ich würde zusehen, es sauber hinzubekommen und keine Prozeduren und Methoden zwangsweise zu verheiraten.
Du findest hier übrigens einen Artikel zu Komponentenarrays von mir, das könnte Dir auch noch weiterhelfen.
Grüße
Christian
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|