Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi eigenem Objekt Ereignisse hinzufügen (https://www.delphipraxis.net/124061-eigenem-objekt-ereignisse-hinzufuegen.html)

Gargamel 13. Nov 2008 21:37


eigenem Objekt Ereignisse hinzufügen
 
Hi

Ich beschäftige mich gerade etwas näher mit OOP. Funktioniert auch soweit ganz gut. Jetzt hätte ich gern gewußt, wie man seinem eigenen Objekt Ereignisse spendieren kann.
In der Hilfe stand irgendwas von TNotifyEvent, nur leider ist da bei mir Feierabend. :wall:
Nehmen wir einfach mal an, daß ein Ereignis ausgelöst werden soll, wenn der Name der Person geändert wird. Was müßte ich da machen?

Delphi-Quellcode:
unit Unit_Main;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

  TPerson = class
  private
    Name:string;
    FirstName:string;
  public
    constructor Create();
    procedure setName(newName:string);
    procedure setFirstName(newFirstname:string);
    function getName():string;
    function getFirstName():string;
  end;

var
  Form1: TForm1;
  Person:TPerson;

implementation

{$R *.dfm}

constructor TPerson.Create;
begin
  inherited create;
  Name:='';
  FirstName:='';
end;

procedure TPerson.setName(newName:string);
begin
  Name:=newName;
end;

procedure TPerson.setFirstName(newFirstName:string);
Begin
  FirstName:=newFirstName;
End;

function TPerson.getName():string;
Begin
  result:=Name;
end;

function TPerson.getFirstName():string;
Begin
  result:=FirstName;
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Person:=TPerson.Create;
  Person.setName('Test_Nachname');
  Person.setFirstName('Test_Vorname');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Listbox1.Clear;
  Listbox1.Items.add(Person.getName());
  Listbox1.Items.add(Person.getFirstName());
end;

end.

Sir Rufo 13. Nov 2008 22:06

Re: eigenem Objekt Ereignisse hinzufügen
 
Hi,

so muss das aussehen
Delphi-Quellcode:
unit Unit_Main;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
    procedure NameWurdeGeaendert1( Sender : TObject );
    procedure NameWurdeGeaendert2( Sender : TObject; VName, NName : string );
  public
    { Public-Deklarationen }
  end;
 
  TNotifyPersonEvent = procedure( Sender : TObject; VName, NName : string ) of object;

  TPerson = class
  private
    FNName:string;
    FVName:string;
    FOnNameChange1 : TNotifyEvent; // Definition für TNotifyEvent = procedure( Sender : TObject ) of object;
    FOnNameChange2 : TNotifyPersonEvent;
    procedure SetVName( Value : string );
    procedure SetNName( Value : string );
    procedure SetOnNameChange1( Value : TNotifyEvent );
    procedure SetOnNameChange2( Value : TNotifyPersonEvent );
  public
    // Mit property geht das viel schöner :-)
    // den private Bereich mal komplett leer lassen, dann
    // einfach nur diese Zeilen eintippen und dann
    // Shift-Ctrl-C drücken (Code-Completion) und staunen ;-)
    property VName : string read FVName write SetVName;
    property NName : string read FNName write SetNName;
    property OnNameChange1 : TNotifyEvent read FOnNameChange1 write SetOnNameChange1;
    property OnNameChange2 : TNotifyPersonEvent read FOnNameChange1 write SetOnNameChange1;
    constructor Create;
  end;

var
  Form1: TForm1;
  Person:TPerson;

implementation

{$R *.dfm}

constructor TPerson.Create;
begin
  inherited Create;
  FNName := '';
  FVName := '';
end;

procedure TPerson.SetVName( Value : string );
begin
  FVName := Value;
  if Assigned( FOnChangeName1 ) // ist das Gleiche wie: if FOnChangeName1 <> nil
  then
    FOnChangeName1( Self );
  if Assigned( FOnChangeName2 )
  then
    FOnChangeName2( Self, FVName, FNName );
end;

procedure TPerson.SetNName( Value : string );
begin
  FNName := Value;
  if Assigned( FOnChangeName1 )
  then
    FOnChangeName1( Self );
  if Assigned( FOnChangeName2 )
  then
    FOnChangeName2( Self, FVName, FNName );
end;

procedure TPerson.SetOnNameChange1( Value : TNotifyEvent );
begin
  FOnNameChange1 := Value;
end;

procedure TPerson.SetOnNameChange2( Value : TNotifyPersonEvent );
begin
  FOnNameChange2 := Value;
end;

procedure TForm1.NameWurdeGeaendert1( Sender : TObject );
begin
  ShowMessage( 'Der Name wurde geändert!' );
end;

procedure TForm1.NameWurdeGeaendert2( Sender : TObject; VName, NName : string );
begin
  ShowMessage( 'Der Name wurde auf ' + VName + ' ' + NName + ' geändert!' );
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Person:=TPerson.Create;

  Person.OnNameChange1 := NameWurdeGeaendert1;
  Person.OnNameChange2 := NameWurdeGeaendert2;
 
  Person.setName('Test_Nachname');
  Person.setFirstName('Test_Vorname');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Listbox1.Clear;
  Listbox1.Items.add(Person.getName());
  Listbox1.Items.add(Person.getFirstName());
end;

end.
cu

Oliver

Gargamel 13. Nov 2008 22:31

Re: eigenem Objekt Ereignisse hinzufügen
 
Na das nenne ich mal eine prompte Bedienung. Einige Zeilen sind mir nicht ganz klar, aber das werde ich noch herausfinden.

Vielen Dank

Sir Rufo 13. Nov 2008 22:35

Re: eigenem Objekt Ereignisse hinzufügen
 
Zitat:

Zitat von Gargamel
Na das nenne ich mal eine prompte Bedienung. Einige Zeilen sind mir nicht ganz klar, aber das werde ich noch herausfinden.

Vielen Dank

Bitte bitte, sonst frag halt welche ... oder markiere die Zeilen mit einem Fragezeichen ...

cu

Oliver

Gargamel 16. Nov 2008 15:47

Re: eigenem Objekt Ereignisse hinzufügen
 
Hi

Ja, ein paar Sachen sind mir noch nicht ganz klar.

Zeile 24: Wozu wurde TNotifyPersonEvent deklariert?

Zeile 44: Müßte das nicht FOnNameChange2 und SetOnNameChange2 lauten?


Zeile 41-44:
Ich vermute, daß es property wegen dem Objektinspektor gibt, damit eine Wertzuweisung intern einen Funktionsaufruf zur Folge hat (via read und write hinter der property-Eigenschaft).

Zeile 109: Hier wird die Funktion definiert, die bei Ereignis XY ausgeführt werden soll?


Das Zusammenspiel von SetVName, SetOnNameChange1 und FOnNameChange ist mir noch nicht ganz klar.

Sir Rufo 16. Nov 2008 16:24

Re: eigenem Objekt Ereignisse hinzufügen
 
Zitat:

Zitat von Gargamel
Hi

Ja, ein paar Sachen sind mir noch nicht ganz klar.

Zitat:

Zitat von Gargamel
Zeile 24: Wozu wurde TNotifyPersonEvent deklariert?

Um einen eigenen EventType zu deklarieren. Mit TNotifyEvent kann ich nur Sender als Parameter übergeben.
Will ich mehr übergeben, dann macht man das so. Mit diesem Event kann ich also hier auch gleich VName und NName übergeben. (so geschieht in Zeile 82)

Zitat:

Zitat von Gargamel
Zeile 44: Müßte das nicht FOnNameChange2 und SetOnNameChange2 lauten?

ja :oops: bitte ändern ;-)

Zitat:

Zitat von Gargamel
Zeile 41-44:
Ich vermute, daß es property wegen dem Objektinspektor gibt, damit eine Wertzuweisung intern einen Funktionsaufruf zur Folge hat (via read und write hinter der property-Eigenschaft).

Nicht nur das, dadurch kann ich steuern, ob eine Eigenschaft z.b. nur lesend oder nur schreibend ist, und ich kann auf diese Ereignisse auch noch reagieren. Der Vorteil ist, dass bei der Benutzung der Klasse einfach einer anscheinlichen Variablen der Klasse ein Wert zugewiesen wird, was die Programmierung wesentlich erleichtert. Also statt GetVariable und SetVariable arbeite ich einfach mit Variable und fertig.

eine Property kann ich auch wie folgt deklarieren:
Delphi-Quellcode:
private
  FVar : integer;
  function GetVar : integer;
  procedure SetVar( Value : integer);
public
  property Var1 : integer read GetVar write SetVar; // Lesen und Schreiben via func/proc
  property Var2 : integer read FVar;               // Nur Lesen direkt
  property Var3 : integer write FVar;              // Nur Schreiben direkt
  property Var4 : integer read GetVar; write FVar; // Lesen via func, Schreiben direkt
Zitat:

Zitat von Gargamel
Zeile 109: Hier wird die Funktion definiert, die bei Ereignis XY ausgeführt werden soll?

Nein, definiert wird die in Zeile 95.
In Zeile 109 wird diese procedure an die Klasse gehängt.
Ausgeführt wird die, wenn die Klasse den Event feuert (Zeile 68/79), darum wird auch in Zeile 66/77 überprüft, ob für dieses Event auch ein Ziel angegeben wurde.

Zitat:

Zitat von Gargamel
Das Zusammenspiel von SetVName, SetOnNameChange1 und FOnNameChange ist mir noch nicht ganz klar.

Wenn Person.VName := 'Peter' ausgeführt wird, dann wird die proc TPerson.SetVName( 'Peter' ) aufgerufen.
Hier wird der Variablen TPeter.FVName der Wert 'Peter' zugewiesen.
Dann werden die Events gefeuert.

Wenn du das Programm mal ausführst, dann solltest du eigentlich sehen, was da passiert.
Vor allem kommentiere doch mal wahlweise die Zeile 109 und 110 aus und schau was passiert.

cu

Oliver


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:42 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