Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Ereignis einer zur Laufzeit erstellten Klasse


Schatten^parker - Sa 14.09.02 18:31
Titel: Ereignis einer zur Laufzeit erstellten Klasse
Hi Leute ich hab ein Problem.
Ich habe eine Klasse Timage geschaffen die zur laufzeit erstellt wird. Jedoch kann man somit keine Ereignisse in die Images Implementieren.
Meine Frage nun, wie kann ich einer klasse ein onclick Ereignis zuordnen.

und wie sendet mir diese komponente ihren namen zurück.

danke


LCS - Sa 14.09.02 18:49

Hi
Hast du nun eine neue Klasse erstellt (dann wäre TImage ein denkbar schlechter Name) oder hast du ein Objekt vom Typ TImage in deinem Programm erzeugt?
Ich geh mal einfach vom zweiten aus. Dann musst du natürlich deine Ereignisprozeduren auch zur Laufzeit zuweisen. Die Prozedur brauchst du natürlich erst mal:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
type
  TForm1 = class(TForm)
  ...
    procedure ImgClick(Sender: TObject);
  ...
  ...

procedure TForm1.ImgClick(Sender: TObject);
begin
  ...
end;

Wenn du dein Objekt erstellt hast, kannst du diese Prozedur zuweisen

Quelltext
1:
2:
3:
...
MeinErstelltesImage.OnClick := ImgClick;
...

Den Namen eines Objekts liefert die Eigenschaft Name. So du nach dem Erstellen überhaupt einen zugewiesen hast.

Gruss Lothar


Schatten^parker - So 15.09.02 13:49
Titel: naja weiss nicht .....
TKarte = class(TImage)
somit habe ich eine klasse Timage erstellt die proceduren und so'n zeugs beinhaltet

jetzt werden aber zur laufzeit Objekte der Klasse(Timage) erschaffen deren namen ich nicht festlege, nur Position auf dem Formular und Bildquelle werden festgelegt. Und ich moechte das wenn man auf ein Image klickt eine Procedure aufgerufen wird, also durch ein Ereignis.

Vielleicht kannst du dir besser Vorstellen wenn du weisst das es ein Memmory Spiel werden soll bei dem alle Karten zur Laufzeit erzeugt werden.


DeCodeGuru - So 15.09.02 14:16

Ich habe es jetzt zwar nicht so ganz verstanden. Nehmen wir an, du erstellt deine Objekte (is ja egal ob TImage oder irgendeine abgeleitete Klasse) in einem Array. Also in etwa so:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var
  i: Integer;
  ImageArray: array [0..9] of TImage;
begin
  for i := 0 to 9 do
  begin
    ImageArray[i] := TImage.Create;
    with ImageArray[i] do
    begin
      ... //Hier Position und sowas angeben. Im Moment uninteressant
    end;
  end;
end;


Wenn du jetzt auf ein Bildchen klickst so zum Beispiel folgende Prozedure ausgelöst werden:


Quelltext
1:
2:
3:
4:
procedure TForm.DoClick(Sender: TObject);
begin
  ShowMessage('Klick');
end;


Damit diese Prozedur ausgelöst wird, musst du das OnClick-Ereignis, der erstellten Objekte mit der Prozedure verknüpfen. Dazu nehmen wird den ersten Code und fügen etwas hinzu:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
var
  i: Integer;
  ImageArray: array [0..9] of TImage;
begin
  for i := 0 to 9 do
  begin
    ImageArray[i] := TImage.Create;
    with ImageArray[i] do
    begin
      ... //Und hier wieder die Posangaben und was weiss ich nicht alles
      OnClick := DoClick;
    end;
  end;
end;


Damit du aber die Images unterscheiden kannst, also, damit du unterscheiden kannst auf welches Image jetzt geklickt wurde, würde ich denen Namen vergeben. Das könnte man so machen (den Code anstelle des '...' einfügen):


Quelltext
1:
Name := 'MyImage'+i;                    


Somit hast du den Images einen eindeutigen Namen zugewiesen. Damit kannst du auch in der DoClick-Prozedure die Images unterscheiden.

Ich hoffe, ich konnte dir ein bisschen helfen bzw. dir die Sache verdeutlichen :wink:


Schatten^parker - So 15.09.02 20:56

Das ist ja alles ganz toll mit den array und so aber ich möchte das ohne sie machen. Ich moechte den Karte der Klasse Timage auch keine namen zuweisen.

Ich moechte lediglich eine Ereignisprocedure implementieren die beim klick auf die Images aufgerufen wird. Da die Images zur laufzeit erschaffen werden kann ich ihnen über den Objektinspektor keine Ereignisse zuteilen.

hier ist mal der code (newbie code also nicht lachen), vielleicht wisst ihr dann besser was ich moechte.

Der Code ist noch nicht lauffähig und die Erschaffung der Karten ist noch umständlich aber dieses Problem behebe ich später.....
Wie gesagt es handelt sich um ein MemmorySpiel, soll es jedenfalls mal werden.... DANKE!!!!!!!!!


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:
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:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
unit Unit1;

interface

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

type
  TKarte = class(TImage)
  private


  bildname : string;
  public

  procedure bildladen;
  procedure karteverdecken;
  procedure Karteaufdecken;
  Procedure Vergleichen;
  Procedure Punktezuweisen;
  Procedure Kartenloeschen;


  end;

type
  TFrm_Memmory = class(TForm)
    T_vergleichen: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure T_vergleichenTimer(Sender: TObject);

  private
    karte1,karte2,karte3 : Tkarte;
    { Private-Deklarationen }
  public

    { Public-Deklarationen }
  end;

var
  Frm_Memmory: TFrm_Memmory;
  karte: Tkarte;

implementation


procedure TKarte.bildladen;
begin
  self.Picture.LoadFromFile(self.bildname);

end;



procedure TKarte.karteverdecken;
begin
        self.visible:=false;
end;



procedure Tkarte.Karteaufdecken;
begin
        self.Visible:= true;
end;



Procedure tkarte.Vergleichen;
begin

end;



Procedure tkarte.Punktezuweisen;
begin
        If KARTE1.picture = KARTE2.Picture then do
        begin
        punktezuweisen;
        Kartenloeschen;
        end
                else
                tfrm_memmory.T_vergleichen.enabled:= false;
                        

end;


{$R *.DFM}
procedure TFrm_Memmory.FormCreate(Sender: TObject);
begin
karte1 := tkarte.Create(self);
karte1.Parent := self;
karte1.bildname := 'bilder\karte1.bmp';
karte1.bildladen;
karte2 := tkarte.Create(self);
karte2.Parent := self;
karte2.bildname := 'bilder\karte1.bmp';
karte2.bildladen;
karte2.Left := 100;
karte3 := tkarte.Create(self);
karte3.Parent := self;
karte3.bildname := 'bilder\karte2.bmp';
karte3.bildladen;
karte3.Left := 200;
end;



procedure TFrm_Memmory.T_vergleichenTimer(Sender: TObject);
begin
        KARTE1.Visible:= False;
        KARTE2.Visible:= False;
        T_vergleichen.enabled:= false;
end;

end.


Tino - So 15.09.02 21:45

Schatten^parker hat folgendes geschrieben:
Ich moechte lediglich eine Ereignisprocedure implementieren die beim klick auf die Images aufgerufen wird.


Wie das geht hat LCS schon gepostet:

Quelltext
1:
MeinErstelltesImage.OnClick := ImgClick;                    


Außerdem hat es DeCodeGuru nochmals erklärt:

Quelltext
1:
OnClick := DoClick;                    


Gruß
TINO


Schatten^parker - Mo 16.09.02 12:08

HarHarHar, es hat funktioniert, danke nochmal an alle


Schatten^parker - Mo 16.09.02 18:56

Hab noch ne Frage, wenn ich nun auf die Karte Klicke, moechte ich dass mir der name der Karte zurückgeliefert oder in einer variablen gespeichert wird.
Wie die Karten erzeugt werden könnt ihr oben in meinem Quelltext nachlesen,
ist zwar etwas umständlich aber für den moment soll das so bleiben.


aogwaba - Mo 16.09.02 20:50

Hi!


Quelltext
1:
2:
3:
4:
5:
6:
var KartenName:string;

procedure  TFrm_Memmory .Karte_wurde_angeklickt(sender:TObject);
begin
if sender is TKarte then KartenName:=sender.name;
end;


cu
waba


LCS - Di 17.09.02 07:52

Hi
kleine Korrektur:

Quelltext
1:
2:
3:
4:
5:
6:
var KartenName:string; 

procedure  TFrm_Memmory .Karte_wurde_angeklickt(sender:TObject); 
begin 
if sender is TKarte then KartenName:=TKarte(sender).name; 
end;

Sender ist ja als TObject deklariert und die gibts keine Eigenschaft Name.
Aber: Wenn du einen Namen willst, musst du deinen Objekten beim Erstellen erst mal nen Namen verpassen. Wurde weiter oben schon von DeCodeGuru beschrieben. Wenn du keine Arrays verwenden willst:

Quelltext
1:
2:
3:
4:
5:
...
karte2 := tkarte.Create(self); 
karte2.Parent := self; 
karte2.Name  := 'Karte2';
...


Gruss Lothar


aogwaba - Di 17.09.02 15:31

Hi!
Nee, das ist schon richtig. Für das Vorhandensein des Name-Property sorgt ja der Vorgänger der TKarte->TImage. 'is' checkt ja die Instanz des Object's nicht die des Typ's.

Quelltext
1:
2:
3:
var myObject:TObject;
myObject:=TImage.create(self);
if (myObject is timage) then ...

cu
waba


LCS - Di 17.09.02 18:33

Hi
Zitat:

Für das Vorhandensein des Name-Property sorgt ja der Vorgänger der TKarte->TImage.

Nix dagegen einzuwenden. Trotzdem wird es ja zunächst mal vom Typ TObject übergeben. Die Eigenschaft Name ist zwar vorhanden, aber du kannst sie erst ansprechen, wenn du TObject wieder in TKarte castet. Versuchst du direkt Sender.Name ergibt das:
Zitat:

[Fehler] Unit1.pas(31): Undefinierter Bezeichner: 'Name'


Gruss Lothar


aogwaba - Di 17.09.02 19:04

Hi!
Hast recht, der Typcst fehlt:


Quelltext
1:
if sender is TKarte then KartenName:=(sender as TKarte).name;                    


cu
waba