do a chronometer in countdown delphi

1

Greetings, I've been wondering how to put a countdown of a minute or a chronometer to say it and then join it to a traffic light that I made with forms and timers for when you start for example this is in red for 59 seconds then turn to yellow and so on. So far I have only been able to make the semaphores in bold change between them. here my progress:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Interval := 2500;
timer2.Interval := 3000;
timer3.Interval := 1500;
shape3.Brush.Color := clGreen;
shape2.Brush.Color := clOlive;
shape1.Brush.Color := clRed;
timer1.Enabled := false;
timer2.Enabled := true;
timer3.Enabled := false;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin

shape2.Brush.Color := clYellow;
shape1.brush.Color := clMaroon;
timer2.Enabled := false;
Timer3.Enabled :=  true;
end;

procedure TForm1.Timer3Timer(Sender: TObject);
begin
shape3.Brush.Color := clLime;
shape2.Brush.Color := clOlive;
shape1.Brush.Color := clMaroon;
timer1.Enabled := true;
    
asked by Jose Guillermo Cordero Garcia 16.02.2017 в 19:20
source

1 answer

1

Since you mentioned a semaphore and a countdown timer, I made a small functional example, although using the TTimer, not in the same way as you put it in the question.

First, let's see the traffic light working:

I've done it using Firemonkey, but the basic idea is the same if you use VCL.

I have a form with 3 TCircle , which will be the lights of the traffic light. A TStopWatch of the unit Diagnostics , which is what helps me keep track of elapsed time, and a TTimer established at a 50ms interval.

The OnTimer event is this:

procedure TForm1.tTiempoTimer(Sender: TObject);
begin
  if FStopWatch.ElapsedMilliseconds > FSegundosAEsperar * 1000 then
    CambiarDeColor;
  ActualizarEtiqueta;
end;

As you can see, this event handler pulls these two methods:

procedure TForm1.CambiarDeColor;
begin
  case FColorEncendido of
    Verde: EstablecerColor(Amarillo, SegundosAmarillo);
    Amarillo: EstablecerColor(Rojo, SegundosRojo);
    Rojo: EstablecerColor(Verde, SegundosVerde);
  end;
end;

procedure TForm1.ActualizarEtiqueta;
var
  FaltaMSec: Int64;
  Min, Sec: Word;
begin
  FaltaMSec := FSegundosAEsperar * 1000 - FStopWatch.ElapsedMilliseconds + 950;
  Sec := (FaltaMSec div 1000) mod 60;
  Min := (FaltaMSec div 1000) div 60;
  lblTiempo.Text := Format('%.2d:%.2d', [Min, Sec]);
end;

The CambiarDeColor method has the basic logic of the semaphore operation, and the ActualizarEtiqueta method of the countdown timer operation. For the operation of the latter, I store in a member of the class the waiting time of the light in progress, and the first line of the method obtains the difference between the time to be expected and the elapsed time, plus a little less than a second, since otherwise the chronometer would show the text '00: 00 'for a whole second before the color change, and it is not the behavior expected by the user.

Finally, the EstablecerColor method is responsible for adjusting the colors of the semaphore each time a color change occurs, and restarting the FStopWatch so that the count of the time elapsed from 0 starts again.

procedure TForm1.EstablecerColor(AColor: TColorSemaforo; ASegundos: Integer);
var
  cRojo: TAlphaColor;
  cAmarillo: TAlphaColor;
  cVerde: TAlphaColor;
  cEtiqueta: TAlphaColor;
begin
  FColorEncendido := AColor;
  cRojo := TAlphaColorRec.Indianred;
  cAmarillo := TAlphaColorRec.Palegoldenrod;
  cVerde := TAlphaColorRec.Darkseagreen;
  cEtiqueta := TAlphaColorRec.Silver;
  case AColor of
    Verde:
      begin
        cVerde := TAlphaColorRec.Lime;
        cEtiqueta := cVerde;
      end;
    Amarillo:
      begin
        cAmarillo := TAlphaColorRec.Yellow;
        cEtiqueta := cAmarillo;
      end;
    Rojo:
      begin
        cRojo := TAlphaColorRec.Red;
        cEtiqueta := cRojo;
      end;
  end;
  LuzRoja.Fill.Color := cRojo;
  LuzAmarilla.Fill.Color := cAmarillo;
  LuzVerde.Fill.Color := cVerde;
  lblTiempo.TextSettings.FontColor := cEtiqueta;
  FStopWatch.Reset;
  FStopWatch.Start;
  FSegundosAEsperar := ASegundos;
end;

Finally, the declaration of the class:

type
  TForm1 = class(TForm)
    LuzRoja: TCircle;
    LuzAmarilla: TCircle;
    LuzVerde: TCircle;
    lblTiempo: TLabel;
    tTiempo: TTimer;
    procedure tTiempoTimer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    const
      SegundosVerde = 7;
      SegundosAmarillo = 3;
      SegundosRojo = 10;
    type
      TColorSemaforo = (Verde, Amarillo, Rojo);
    var
      FColorEncendido: TColorSemaforo;
      FStopWatch: TStopWatch;
      FSegundosAEsperar: Integer;
    procedure EstablecerColor(AColor: TColorSemaforo; ASegundos: Integer);
    procedure CambiarDeColor;
    procedure ActualizarEtiqueta;
  public
  end;

The result is the one you see in the image above, which I made with a screenshot after executing this project.

    
answered by 22.02.2017 в 23:40