Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Timer und Laufzeit (https://www.delphipraxis.net/151487-timer-und-laufzeit.html)

Privateer3000 19. Mai 2010 23:14


Timer und Laufzeit
 
Wenn zur Laufzeit einer oder mehrere Timer erstellt werden,
wie verfährt man dann mit den zugehörigen OnTimer Ereignis?
Jeder Timer hat ja normalerweise sein eigenes Ereignis, wie nun
wenn doch dieser erst erstellt wird?
Muss man eine proc oder function für alle Timer zuweisen?
Irgenwie fehlt mir der Draht...

s.h.a.r.k 19. Mai 2010 23:26

Re: Timer und Laufzeit
 
Du musst schon vorher die Methode schreiben, die vom Timer aufgerufen werden soll. Dann kannst du es wie folgt machen:

Delphi-Quellcode:
TForm1 = class(TForm)
private
  procedure MyTimerMethodA(Sender: TObject);
  procedure MyTimerMethodB(Sender: TObject);
end;

{ ... }

procedure TForm1.MyTimerMethodA(Sender: TObject);
begin
  //
  // hier dein Code
  //

  // Vielleicht noch ein Umbiegen der Methode, die beim
  // Feuern des Timers aufgerufen werden soll ;)
  TTimer(Sender).OnTimer := MyTimerMethodB;
end;

procedure TForm1.MyTimerMethodB(Sender: TObject);
begin
  //
  // hier dein Code
  //
end;

{ ... }

var
  newTimer : TTimer;
begin
  newTimer := TTimer.Create(nil);
  newTimer.Enabled := False;
  newTimer.Interval := 1000;
  newTimer.OnTimer := MyTimerMethod; // hier die Zuweisung der passenden Methode
  newTimer.Enabled := True;
end;

Privateer3000 19. Mai 2010 23:38

Re: Timer und Laufzeit
 
Ok, Danke.
Also reicht eine publike proc für alle Timer?!
Denn nicht alle Timer arbeiten ja gleichzeitig.

Insgesamt soll will ich sowas für unseren Club machen.
Sowas wie Schachuhren, zu jeden Timer gibts
1 Label (Zeit),1 Label (Punkte) und einen Button (Start/Stop).
Da die Anzahl variabel ist, erzeuge ich halt erst dann alle
Kompos, statt ne feste Menge.

Im Ontimer wird halt dann für jeden Timer die abgelaufene
Zeit usw. ermittelt und angezeigt.

sx2008 20. Mai 2010 00:21

Re: Timer und Laufzeit
 
Für viele Schachuhren braucht man eigentlich nur einen Timer.
Dieser Timer ist nur dafür zuständig alle 0,2s die Anzeige sämlicher Schachuhren zu aktualisieren.
Eine einzelne Schachuhr könnte z.B. so aussehen:
Delphi-Quellcode:
TChessClock = class(TObject)
private
  FLastStart : TDateTime;
  FSummeZeit : TDateTime; // 1.0 entspricht einem Tag, 0.04166= eine Stunde
  FRunning : Boolean;
public
  procedure Start;
  procedure Stop;
  procedure Reset;

  function GetSummezeit:TDateTime; // liefert die aufgelaufene Zeit
  function GetSummeZeitAsString:string;

  property Running : Boolean read FRunning;
end;
...
function TChessClock.GetSummezeit:TDateTime;
begin
  if Running then
    result := FSummeZeit + (Now-FLastStart)
  else
    result := FSummeZeit;
end;
Zu Beginn ist SummeZeit = 0. Wird die Uhr gestartet, dann wird die aktuelle Uhrzeit+Datum (Funktion Now benützen) im Feld FLastStart gespeichert.
Wird die Uhr gestoppt, dann wird intern gerechnet:
Delphi-Quellcode:
FSummeZeit := FSummeZeit + (Now - FLastStart);
Man kann die Uhr auch so designen, dass mit einer Zeitvorgabe (z.B. 10Min) gestartet wird und dann dieses Zeitguthaben verkleinert wird.

Für ein Schachspiel müssen zwei Uhren zusammengenommen werden.
Hier würde ich eine weitere Klasse verwenden, um zwei Objekte von TChessClock zusammenzufassen.
Beim Stop der einen Uhr startet wird automatisch die Uhr des Gegners gestartet.
Dann kann man beliebig viele Objekte dieser Doppeluhren in einer TObjectList oder in einem dyn. Array anlegen.
Der Timer hat dann "nur" noch die Aufgabe, alle Doppeluhren aus der Liste auszulesen und im Formular anzuzeigen.

Privateer3000 20. Mai 2010 23:19

Re: Timer und Laufzeit
 
Danke für die Tipps,
aber genau daran hängt es.
Zitat:

Der Timer hat dann "nur" noch die Aufgabe, alle Doppeluhren aus der Liste auszulesen und im Formular anzuzeigen.
Was muss in der Timerprozedur ablaufen? Ich habe einfach keine Idee, wie das aussehen soll.
Ich habe jedem Label (Zeit) einen eindeutigen Tag zugwiesen, soll die die Tags
in ein Array stopfen, oder die Labels in eine Objektliste?

:(

sx2008 22. Mai 2010 00:28

Re: Timer und Laufzeit
 
Zitat:

Zitat von Privateer3000
Was muss in der Timerprozedur ablaufen? Ich habe einfach keine Idee, wie das aussehen soll.
Ich habe jedem Label (Zeit) einen eindeutigen Tag zugwiesen, soll die die Tags
in ein Array stopfen, oder die Labels in eine Objektliste?

Wie man das macht ist auch ein bisschen Geschmackssache.
Aber ich würde hier zu "höherwertigen" Datenstrukturen wie Objektlisten greifen und (dynamische) Arrays mehr "in der Tiefe", also verborgen in Klassen, verwenden.
Aber Dir fehlt im Grunde genommen noch eine Klasse.
Diese Klasse dient als Adapter zwischen der Doppeluhr und den Controls der Benutzeroberfläche.
Es sieht erstmal nach mehr Arbeit aus, aber dafür vereinfacht sich der Code im Formular.
Hier mal ganz grob diese Klasse:
Delphi-Quellcode:
TGameClockAdapter=class(TObject)

public
  GameClock : TGameClock; // die Doppeluhr
  LabelPlayerA : TLabel; // Zeitanzeige Spieler A
  LabelPlayerB : TLabel; // Zeitanzeige Spieler B
  LabelStatus : TLabel;  // Anzeige, welcher Spieler am Zug ist
 
  destructor Destroy;override;
  procedure RefreshUserInterface;
  procedure StartNewGame;
  procedure PauseGame;
  ...
end;
...
procedure TGameClockAdapter.RefreshUserInterface;
begin
  LabelPlayerA.Caption := GameClock.PlayerA.GetSummeZeitAsString;
  LabelPlayerB.Caption := GameClock.PlayerB.GetSummeZeitAsString;
  if GameClock.PlayerA.Running then
    LabelStatus.Caption := 'Spieler A am Zug'
  else
    LabelStatus.Caption := 'Spieler B am Zug'
end;

destructor TGameClockAdapter.Destroy;
begin
  GameClock.Free;
  inherited;
end;
Das mit dem Status-Label kann man natürlich auch schöner machen; z.B. Namen des Spielers anzeigen und zusätzlich mit zwei Icons anzeigen, welcher Spieler am Zug ist.

Der Ablauf sieht so aus:

Objekte von TGameClockAdapter erzeugen, jeweils ein GameClock-Objekt erzeugen und dem TGameClockAdapter-Objekt mitgeben.
Dann die 3 Labels zuweisen.
Diese TGameClockAdapter Objekte werden nun in einer Objektliste gespeichert.

Und dann noch der Eventhandler für den Timer:
Delphi-Quellcode:
procedure TForm1.TimerAllTimer(Sender:TObject)
var
  i : integer;
begin
  // Azeige für alle Doppeluhren aktualisieren
  for i := 0 to FGameClockList.Count-1 do
  begin
    (FGameClockList.Objects[i] as TGameClockAdapter).RefreshUserInterface;
  end;
end;


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