Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TNotifyEvent mit zusätzlichen Parametern ? (https://www.delphipraxis.net/171016-tnotifyevent-mit-zusaetzlichen-parametern.html)

MrMooed 15. Okt 2012 18:52

Delphi-Version: 7

TNotifyEvent mit zusätzlichen Parametern ?
 
Guten Abend DP,

ich bin immernoch dabei eine Art 'Tron' zu programmieren und bin erneut an meine Grenzen gestoßen :?

In dem Project soll jedes Fahrzeug (Bike) einen Timer bekommen mit dem es sich bewegt. (Jeder einen eigenen, damit sie sich unterschiedlich schnell bewegen können) Nun kreiere ich meine Timer dynamisch und weise ihnen das .OnTimer Event zu. Allerdings möchte ich, dass die procedur sich unterschiedlich verhällt, je nach dem welcher Timer das Event ausgelöst hat.

Doch nun stellt sich mir das Problem, dass ich einem TNotifyEvent keine Parameter übergeben kann und somit nicht feststellen kann wer es ausgelöst hat :|
Mein Wissen

Deklaration:
Delphi-Quellcode:
Timer: Array of TTimer;
Tasten: TQueue;
Bike: Array of TBike;
Erstellung der Timer:
Delphi-Quellcode:
for i:=0 to Pred(pTimerAnzahl) do begin
    SetLength(Timer, Succ(i));
    Timer[i] := TTimer.Create(nil);
    Timer[i].Interval := 10;
    Timer[i].OnTimer := onTimer(Timer[i], i);
    Timer[i].Enabled := True;
    end;
onTimer:
Delphi-Quellcode:
procedure TSpielfeld.onTimer(Sender: TObject);
begin
  if Sender = Timer[0]
    then if Tasten.Count > 0
           then
             case Word(Tasten.Pop) of
               70: Bike[0].dreheLinks;
               74: Bike[0].dreheRechts;
               end;
  (Sender as TTimer).Enabled := False;
  bewegeBikes(Sender);//stellt nach Bewegung (Sender as TTimer).Enabled := True
  .
  .
end;

Sir Rufo 15. Okt 2012 18:56

AW: TNotifyEvent mit zusätzlichen Parametern ?
 
Also beim NotifyEvent wird doch der Auslöser mitgegeben -> Sender

Bummi 15. Okt 2012 19:16

AW: TNotifyEvent mit zusätzlichen Parametern ?
 
Das Konzept der vielen Timer ist sicher sehr ungünstig, aber weil es Spass macht auch mal etwas um die Ecke zu programmieren .... bitte nicht so umsetzen.

Du brauchst nur einen Timer in dem die Zustände aller Fahrzeuge abzufragen un zu ändern .... also just 4 fun:

Delphi-Quellcode:
unit Unit3;

interface

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

type
  TBike=Class;
  TTimer=Class(ExtCtrls.TTimer)
    Private
      FMyBike:TBike;
    public
      Property Bike:TBike read FMyBike;
  End;

  TBike=Class (TObject)
      private
      FTimer:TTimer;
      FName: String;
      public
      Constructor Create(const aName:String;aEvent:TNotifyEvent);overload;
      Destructor Destroy;override;
      Property Timer:TTimer read FTimer;
      Property Name:String Read FName;
    end;


  TForm3 = class(TForm)
    Button1: TButton;
    Timer1: TTimer;
    Memo1: TMemo;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
var
 i:Integer;
begin
  for I := 1 to 10 do
    Listbox1.Items.AddObject(Format('Bike %d',[i]),TBike.Create(Format('Bike %d',[i]),Timer1Timer));
end;

{ TBike }

constructor TBike.Create(const aName:String;aEvent: TNotifyEvent);
begin
  inherited Create;
  FTimer := TTimer.Create(nil);
  FTimer.OnTimer := aEvent;
  FTimer.Interval := 50;
  FTimer.FMyBike := self;
  FName := aName;
end;

destructor TBike.Destroy;
begin
  FTimer.Free;
end;

procedure TForm3.FormDestroy(Sender: TObject);
var
 i:Integer;
begin
  for I := Listbox1.Items.Count-1 downto 0 do Listbox1.Items.Objects[i].Free;
  Listbox1.Items.Clear;
end;

procedure TForm3.Timer1Timer(Sender: TObject);
begin
  if Sender is TTimer then
    if Assigned(TTimer(Sender).Bike) then Memo1.Lines.Add(TTimer(Sender).Bike.Name);
end;

end.

MrMooed 15. Okt 2012 19:39

AW: TNotifyEvent mit zusätzlichen Parametern ?
 
Danke für die schnellen Antworten bis jetzt.

@Sir Rufo: Dachte ich zunächst auch, doch als ich im Debuger geguckt habe wo es denn hapert, zeigte er mir an: Sender() also das Sender keinen Wert hat :shock: Müsste ich das on Timer Event dann nich auch anders zuweisen
Delphi-Quellcode:
Timer[i].OnTimer := onTimer(Sender); // das Sender
?


@Bummi: so in der Art habe ich es zur Zeit (mit einem einzigen Timer) doch Sinn und zweck der vershiedenen Timer sollte sein, dass diese auch unterschiedliche Intervalle haben (mit denen die Bewegung unterschiedlic oft ausgeführt wird und sich das Bike somit unterschiedlich schnell bewegt)

Medium 15. Okt 2012 19:44

AW: TNotifyEvent mit zusätzlichen Parametern ?
 
Speicher zu der Position der "Bikes" auch ihre Geschwindigkeit (und Richtung). Dann nimm weiterhin nur einen Timer, aber bewege jedes Bike immer nur um seine eigene Geschwindigkeit in seine eigene Richtung weiter (Geschwindigkeit und Richtung lassen sich i.A. zusammen als ein einziger Vektor darstellen). Das wäre, abgesehen davon, dass Timer hier im Grunde schon eher fragwürdig sind, schon näher an best-practice. (Und es macht auch wirklich Sinn ;))

Sir Rufo 15. Okt 2012 19:52

AW: TNotifyEvent mit zusätzlichen Parametern ?
 
Zitat:

Zitat von MrMooed (Beitrag 1187155)
@Sir Rufo: Dachte ich zunächst auch, doch als ich im Debuger geguckt habe wo es denn hapert, zeigte er mir an: Sender() also das Sender keinen Wert hat :shock: Müsste ich das on Timer Event dann nich auch anders zuweisen
Delphi-Quellcode:
Timer[i].OnTimer := onTimer(Sender); // das Sender
?

Wenn Sender keinen Wert hat, dann zeigt der Debugger nil an.
Da ist zu 99.9999999% genau die Timer-Instanz drin, die das Event aufruft.

Falls du es nicht glaubst:
Delphi-Quellcode:
procedure TSpielfeld.onTimer(Sender: TObject);
begin
  (Sender as TTimer).Enabled := False;
  ShowMessage( Sender.ClassName ); // --> TTimer
  (Sender as TTimer).Enabled := True;
end;
Witzig ist, wenn das nicht so ist, wieso sollte das denn hier (in deinem Code) funktionieren?
Zitat:

Zitat von MrMooed (Beitrag 1187146)
Delphi-Quellcode:
procedure TSpielfeld.onTimer(Sender: TObject);
begin
  if Sender = Timer[0] // <-- ja wenn da nichts in Sender ist
  ...
  (Sender as TTimer).Enabled := False; // <-- ???
  bewegeBikes(Sender);//stellt nach Bewegung (Sender as TTimer).Enabled := True // <-- ???
end;


himitsu 15. Okt 2012 19:57

AW: TNotifyEvent mit zusätzlichen Parametern ?
 
TNotifyEvent hat nunmal nur einen zwei Parameter und daran kann man nichts ändern.

Sender = der Sender (ein Timer)
Self = Empfänger (deine Form)


Nja, wie schon erwähnt, hast du einmal den Sender, und im Sender (TComponent) gibt es noch das Property Tag, welches der Programmierer nach Belieben nutzen kann.


Bezüglich der Arrays, würde ich dir eher zu Listen raten (vorallem die TObjectList).

Und was die Anzahl der Timer angeht, wurde auch schon alles gesagt.

MrMooed 15. Okt 2012 20:05

AW: TNotifyEvent mit zusätzlichen Parametern ?
 
Zitat:

Zitat von Medium (Beitrag 1187157)
Speicher zu der Position der "Bikes" auch ihre Geschwindigkeit (und Richtung). Dann nimm weiterhin nur einen Timer, aber bewege jedes Bike immer nur um seine eigene Geschwindigkeit in seine eigene Richtung weiter (Geschwindigkeit und Richtung lassen sich i.A. zusammen als ein einziger Vektor darstellen). Das wäre, abgesehen davon, dass Timer hier im Grunde schon eher fragwürdig sind, schon näher an best-practice. (Und es macht auch wirklich Sinn ;))

Stimmt so könnte ich das ganze vereinfachen :thumb:

Aber wieso findet du (oder ihr :-D) dass Timer fragwürdig sind ? Wie kann man soetwas sonst realisieren ? :o

glaube Vektoren werde ich mir demnächst mal in Delphi anschauen müssen :oops:

@Sir Rufo:
Delphi-Quellcode:
procedure TSpielfeld.onTimer(Sender: TObject);
begin
  if Sender = Timer[0] // <-- ja wenn da nichts in Sender ist
  ...
  (Sender as TTimer).Enabled := False; // <-- ???
  bewegeBikes(Sender);//stellt nach Bewegung (Sender as TTimer).Enabled := True // <-- ???
end;
ich hatte das Problem, dass der Timer eine Berechnung gestartet hat, doch obwohl er noch nicht fertig mit rechnen war hat der nächste Timer schon losgelegt. Das kam dann zu recht fiesen Fehlern. Ich müsste mal testen ob es immernoch Fehler produziert :roll:


@himitsu:
Wo liegt denn der Vorteil von TObjectList's gegenüber Arrays ? Habe es bisher immer mit Array gemacht :oops:

Sir Rufo 15. Okt 2012 20:08

AW: TNotifyEvent mit zusätzlichen Parametern ?
 
Ich bezog mich darauf, dass du behauptest, in Sender würde nichts enthalten sein (hast du ja mit dem Debugger geprüft) und trotzdem benutzt du den Wert von Sender.

Das wollte ich nur damit aufzeigen, dass in Sender die Timer Instanz enthalten ist

himitsu 15. Okt 2012 23:33

AW: TNotifyEvent mit zusätzlichen Parametern ?
 
viele Timer gegen einen Timer


Du hast nur einen Raum (Thread, in dem eine Person (Timer) gleichzeitig arbeiten kann.
Man kann nun viele Personen (Timer) etwas nacheinander machen lassen
oder manläßt eine Person (Timer) alles nacheinander machen.

Vom Zeitaufwand wird nichts gewonnen, wenn Mehrere arbeiten,
aber der Verwaltungsaufwand wird größer.
- alle Personen (Timer) müssen irgenwo wohnen (Speicher und Resourcen)
- und diese Personen wechseln sich ständig unkontrolierbar ab (extrem schwer zu debugggen, vorallem wenn Mal irgendwas nicht funktioniert)


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