[gelöst] Timer zur Laufzeit in Schleife erzeugen

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
NoCee
Beiträge: 170
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

[gelöst] Timer zur Laufzeit in Schleife erzeugen

Beitrag von NoCee »

Hallo zusammen,
ich möchte mehrere Timer zur Laufzeit erzeugen und hab da was im Netz gefunden und in einer
Schleife erzeugt. Es scheint auch zu funktionieren.
Was ich nicht geschafft (gefunden) habe, ist beim OnTimerevent die Nummer des Timers herrauszubekommen.
Es soll hier nur 1 Procedure aufgerufen werden, in der ich dann auf die verschiedenen Timer reagiere.
Also sowas wie If Sender = Button1 then do xxx oder so was in der Art.
Aber meine Procedure ist ja kein Objekt, mault auf alle Fälle der Kompiler.

Wie könnte ich sowas abfragen?

Code: Alles auswählen

procedure TForm1.MyTimerEvent(Sender: TObject);
begin
   if Timer0 then do xxx; //irgendwie in der Art
   if Timer1 then do yyy;
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
   MyTimer: array[0..5] of TTimer;
   i: integer;
begin
   for i:=0 to 5 do begin
   MyTimer[i] := TTimer.Create(self);
   MyTimer[i].Enabled := True;
   MyTimer[i].Interval := 1000;
   MyTimer[i].OnTimer := @MyTimerEvent;
   end;
 
end;   


Schon mal Danke im Vorraus
Gruß
NoCee
Zuletzt geändert von NoCee am Do 28. Apr 2016, 15:21, insgesamt 1-mal geändert.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Timer zur Laufzeit in Schleife erzeugen

Beitrag von Michl »

Wirf doch dein Array nicht weg, sondern deklariere es in der Formularklasse, dann kannst du sowas machen:

Code: Alles auswählen

  TForm1 = class(TForm)
...
  private
    MyTimer: array[0..5] of TTimer;
...
procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to High(MyTimer) do begin
    MyTimer[i] := TTimer.Create(self);
    MyTimer[i].Enabled := True;
    MyTimer[i].Interval := 1000;
    MyTimer[i].OnTimer := @MyTimerEvent;
  end;
end;
 
procedure TForm1.MyTimerEvent(Sender: TObject);
var
  aTimer: TTimer;
  i: Integer;
begin
  if not Assigned(Sender) then Exit;
  if not (Sender is TTimer) then Exit;
  aTimer := Sender as TTimer;
 
  for i := 0 to High(MyTimer) do
    if aTimer = MyTimer[i] then
      WriteLn('MyTimer[', i, '] aktiv');
end;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

NoCee
Beiträge: 170
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: [gelöst] Timer zur Laufzeit in Schleife erzeugen

Beitrag von NoCee »

Habs ausprobiert.
Genau wie ichs brauche.
Hab mir schon gedacht daß das so in der Art irgendwie ausschauen müßte,
habs aber absolut nicht zusammenbekommen.
Gibt halt noch viel zu lernen :)

Ich danke dir

Einen schönen Tag an alle
NoCee

Warf
Beiträge: 1910
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: [gelöst] Timer zur Laufzeit in Schleife erzeugen

Beitrag von Warf »

Wenn es dir nur um die Nummer geht, jede TComponent abstammende Klasse (also auch TTimer) hat eine property Tag, in der du entweder einen Integer oder einen Pointer speichern kannst, schreib da doch einfach die Nummer rein und dann kannst du im Event via (Sender as TTimer).Tag Auslesen

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: [gelöst] Timer zur Laufzeit in Schleife erzeugen

Beitrag von Mathias »

jede TComponent abstammende Klasse (also auch TTimer) hat eine property Tag,


Das hätte ich auch damit gelöst und sieht dann so aus:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
begin
  for i := 0 to High(MyTimer) do begin
    MyTimer[i] := TTimer.Create(self);
    MyTimer[i].Enabled := True;
    MyTimer[i].Tag := i;
    MyTimer[i].Interval := i * 100; // zur Demo
    MyTimer[i].OnTimer := @MyTimerEvent;
  end;
end;
 
procedure TForm1.MyTimerEvent(Sender: TObject);
begin
  WriteLn('MyTimer[', TTimer(Sender).Tag, '] aktiv');
end;


Die Procedure TimerEvent wird dann so um einiges einfacher.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: [gelöst] Timer zur Laufzeit in Schleife erzeugen

Beitrag von Michl »

Eigentlich wollte ich meine Klappe halten, da hier aber vielleicht auch jemand mitliest, dem die daraus folgenden Konsequenzen evtl. nicht klar sind, nun doch...

Immer wieder, lese ich die Empfehlung IrgendeinTComponent.Tag für irgendwelche Zwecke zu verwenden. Für schnelle Tests habe ich das auch schon gemacht, bei einem ernsthaften Projekt würde ich sowas weitestgehend vermeiden wollen.

Warum?

Zwei Gründe:

- Pascal hat die schöne Eigenschaft klar strukturiert und sehr gut lesbar zu sein. Was sagt mit ein .Tag nach einem halben Jahr? - Nichts. Also fange ich an im Quelltext zu suchen, wo das .Tag gesetzt und verarbeitet wird. Zeit, die mir mit einem klugen Bezeichner gespart geblieben wäre.

- Weil ich heute schnell sein wollte, verwende ich .Tag für das Speichern eines Indizes. Nach einem halben Jahr muss ich die Komponente nochmals anfassen, weil ich das Programm erweitern will. Jetzt will ich mit der Komponente ein anderes Objekt verknüpfen, ah ja, nehme ich doch .Tag und speichere mir die dazugehörige Objektadresse darin. Starte mein Programm und stelle fest, Mist irgendwas geht nicht mehr.

...nur meine unbedeutende Meinung.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Warf
Beiträge: 1910
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: [gelöst] Timer zur Laufzeit in Schleife erzeugen

Beitrag von Warf »

Michl hat geschrieben:Eigentlich wollte ich meine Klappe halten, da hier aber vielleicht auch jemand mitliest, dem die daraus folgenden Konsequenzen evtl. nicht klar sind, nun doch...

Immer wieder, lese ich die Empfehlung IrgendeinTComponent.Tag für irgendwelche Zwecke zu verwenden. Für schnelle Tests habe ich das auch schon gemacht, bei einem ernsthaften Projekt würde ich sowas weitestgehend vermeiden wollen.

Warum?

Zwei Gründe:

- Pascal hat die schöne Eigenschaft klar strukturiert und sehr gut lesbar zu sein. Was sagt mit ein .Tag nach einem halben Jahr? - Nichts. Also fange ich an im Quelltext zu suchen, wo das .Tag gesetzt und verarbeitet wird. Zeit, die mir mit einem klugen Bezeichner gespart geblieben wäre.

- Weil ich heute schnell sein wollte, verwende ich .Tag für das Speichern eines Indizes. Nach einem halben Jahr muss ich die Komponente nochmals anfassen, weil ich das Programm erweitern will. Jetzt will ich mit der Komponente ein anderes Objekt verknüpfen, ah ja, nehme ich doch .Tag und speichere mir die dazugehörige Objektadresse darin. Starte mein Programm und stelle fest, Mist irgendwas geht nicht mehr.

...nur meine unbedeutende Meinung.


Und die Alternative? Helperklassen, neue abstammende klasse schreiben?

Wenn man das konsequent durchziehen würde, z.B. Wenn man verschiedene komponententypen hat, und allen extrainformationen mitgeben möchte könnte man zwar eine Interface schreiben und dann von jeder Klasse eine abstammende klasse mit diesem Interface verwenden, aber da programmiert man sich dumm und dämlich, und grade für nur einen Integer macht das das nicht übersichtlicher

Und wenn man konsequent alles kommentiert was man schreibt ist das rausfinden was der Tag bedeutet auch das geringste Problem

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: [gelöst] Timer zur Laufzeit in Schleife erzeugen

Beitrag von Michl »

Man kann das schon so machen, mir ging es nur darum, dass die Medaille zwei Seiten zur Betrachtung hat.

Eigentlich war ich es erst, der überhaupt den Index in Spiel gebracht hatte, um zu zeigen, dass ein Timer aus dem Array feuert. Oft reicht ein einfaches Casting

Code: Alles auswählen

procedure TForm1.MyTimerEvent(Sender: TObject);
begin
  if not Assigned(Sender) then Exit;
  if not (Sender is TTimer) then Exit;
  TTimer(Sender).IrgendeineMethodeAusfuehren;
end;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

NoCee
Beiträge: 170
Registriert: Do 3. Mär 2011, 21:34
OS, Lazarus, FPC: WinXp/7/10 Opensuse13.2/Leap15.3 (L 2.2.0 FPC 3.2.2 )
CPU-Target: Intel 32/64Bit, ARM9
Wohnort: Ulm

Re: [gelöst] Timer zur Laufzeit in Schleife erzeugen

Beitrag von NoCee »

Aha, interessant.
Ich habs zwar in erster Variante benutzt, aber die Variante mit dem Tag in einem Minimalprogramm
ausprobiert, bin ja schließlich neugierig.

Was ich im Netz jetzt aber nicht erklärt bekommen habe:
Was haben sich das Entwicklerteam dabei gedacht, dieses Tag einzubauen.
Wird das irgend wo gebraucht/benutzt oder ist das einfach da damit ich
wenn ich denn wollte was damit anfangen könnte?

Gruß
NoCee

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: [gelöst] Timer zur Laufzeit in Schleife erzeugen

Beitrag von Mathias »

Wird das irgend wo gebraucht/benutzt oder ist das einfach da damit ich wenn ich denn wollte was damit anfangen könnte?

Dieser steht einem frei zur Verfügung.

Und wenn man konsequent alles kommentiert was man schreibt ist das rausfinden was der Tag bedeutet auch das geringste Problem

Dieser Meinung bin ich auch, vor allem wen man Componenten dynamisch erzeugt.
Setzt man aber Tag-Werte im Object-Inspector, dann kann das ganze recht unübersichtlich werden.
Aber so wie im obigen Beispiel, eine Durchnummerierung einer Array, da bleib es recht übersichtlich.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten