Recent

Author Topic: Wiki TTimer code  (Read 484 times)

dodgebros

  • Full Member
  • ***
  • Posts: 110
Wiki TTimer code
« on: September 28, 2020, 08:32:01 pm »
Below is the code from the Free Psacal wiki for using the ttimer component.  Could someone explain, line by line, how this code works?  An example for why I am posting this is "Why is Dec() function used here? Looks like it should be part of some type of loop"

TD

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. begin
  3.   Label1.Caption := Format('%d sec',[start]);
  4.   Dec(start);
  5.   if (start < 5) then Shape1.Brush.Color:=clYellow;
  6.   if (start < 0) then begin
  7.     Timer1.Enabled := False;
  8.     Shape1.Brush.Color:=clGreen;
  9.     Label1.Caption := 'Finished!';
  10.   end;
  11. end;
  12.  

Bart

  • Hero Member
  • *****
  • Posts: 3952
    • Bart en Mariska's Webstek
Re: Wiki TTimer code
« Reply #1 on: September 28, 2020, 08:37:52 pm »
TForm1.Timer1Timer is executed at intervals (set by Timer1.Interval), so each time it is called, it decrements start.
Then at some point it will color a shape yellow, and later it will color the same shape red.
At that time the toimer will also disable itself, so that TForm1.Timer1Timer is not called anymore.

Dec(SomeOrdinalValue) is the same as SomeOrdinalValue := SomeOrdinalValue - 1.

Bart

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6675
  • Debugger - SynEdit - and more
    • wiki
Re: Wiki TTimer code
« Reply #2 on: September 28, 2020, 08:58:03 pm »
"Why is Dec() function used here? Looks like it should be part of some type of loop"

Well, you probably concluded that this is a count down.

The timer should (probably) fire every 1 seconds.
"start" may begin with 60 (or any value). So the countdown will finish after that many seconds.

And well yes, you could do
Code: Pascal  [Select][+][-]
  1. for start := 60 downto 0 do begin
  2.   // do the countdown
  3.   sleep(1000);
  4. end;

But the loop would mean that your app becomes blocked/unresponsive. The OS may even warn, that your app in not responsive.
Many people still use the loop, and insert "Application.ProcessMessages". That does work. But has it's own drawbacks. For example the time spent in "Application.ProcessMessages" is added to the time waited in "sleep(1000)", and so your loop runs slower than expected.

In modern GUI programming such tasks are solved by an event based implementation. The timer provides the event. And in-between the app runs all normal.

Note, that timers are not a 100% guarantee that there will be never any lag (extra time) added to the cycle. Nor do they necessary happen exactly at the millisecond intended. For a countdown that does not matter. For playing an animation, or frames of a movie, you may need to take extra steps.

BobDog

  • Jr. Member
  • **
  • Posts: 66
Re: Wiki TTimer code
« Reply #3 on: September 28, 2020, 11:45:53 pm »
Windows.
You can guarantee a one millisecond corresponding to a sleep(1) by surrounding sleep with
settimer
sleep(. . .)
freetimer
Thus a 30 second period (near enough),
Code: Pascal  [Select][+][-]
  1.  
  2.     program sleeper;
  3.  
  4.    uses
  5.    SysUtils,DateUtils,crt ;
  6.  Function settimer(i:integer=1):integer;cdecl external 'Winmm.dll' name  'timeBeginPeriod';
  7.  Function freetimer(i:integer=1):integer;cdecl external 'Winmm.dll' name  'timeEndPeriod' ;
  8.  
  9.   Function map(a :double;b :double;_x_ : double;c: double;d: double): double;
  10.  begin
  11.   exit(((d)-(c))*((_x_)-(a))/((b)-(a))+(c));
  12.  End;
  13.  
  14.  
  15.   var
  16.   start:integer;
  17.   StartTime: TTime;
  18.   Elapsed: Int64;
  19.   xpos:double;
  20.   label
  21.   fin;
  22.  begin
  23.  
  24.  writeln('please wait 30 seconds, or press any key to exit early');
  25.  gotoxy(1,10);
  26.  write('[');
  27.   gotoxy(62,10);
  28.  write(']');
  29.    StartTime := Time;
  30.  for start := 30 downto 1 do begin
  31.  
  32.   if (keypressed=true) then goto fin;
  33.   // do the countdown
  34.   xpos:=map(30,1,start,2,60);
  35.   gotoxy(tcrtcoord(trunc(xpos)),10);
  36.   write('__');
  37.  
  38.  
  39.    settimer ;
  40.   sleep(1000);
  41.   freetimer ;
  42.  
  43.  
  44. end;
  45. fin:
  46.  Elapsed := MillisecondsBetween(Time, StartTime);
  47.  writeln ;
  48.  writeln;
  49.   Writeln('Time taken :',elapsed,' milliseconds ');
  50.   writeln('Press return to finish . . .');
  51.   readln;
  52.  end.
  53.  
  54.  
« Last Edit: September 29, 2020, 12:40:34 am by BobDog »

dodgebros

  • Full Member
  • ***
  • Posts: 110
Re: Wiki TTimer code
« Reply #4 on: September 29, 2020, 04:10:50 am »
You guys gave me a lot to think about so let me do some experimenting to try and understand this better.

Thanks to all who replied,
TD

dodgebros

  • Full Member
  • ***
  • Posts: 110
Re: Wiki TTimer code
« Reply #5 on: September 29, 2020, 03:20:38 pm »
TForm1.Timer1Timer is executed at intervals (set by Timer1.Interval), so each time it is called, it decrements start.

Bart

So in the example code Dec(start) would decrease start by 1 but the resultant value of this is lost once the procedure has completed so the next time the procedure is called the value of start would be it's original value.  Am I correct?

TD

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6675
  • Debugger - SynEdit - and more
    • wiki
Re: Wiki TTimer code
« Reply #6 on: September 29, 2020, 03:30:20 pm »
So in the example code Dec(start) would decrease start by 1 but the resultant value of this is lost once the procedure has completed so the next time the procedure is called the value of start would be it's original value.  Am I correct?

No. "start" is not declared a local var. So it should be either global, or better a field on the form "FStart".


I looked up the page https://wiki.lazarus.freepascal.org/TTimer
It says, to add "start" in the private section of TForm1.
It also sets "start := 20;" in the FormCreate event.

IMHO, the wiki could be better, by giving the complete code of the unit, rather than a puzzle on how to put it together.



dodgebros

  • Full Member
  • ***
  • Posts: 110
Re: Wiki TTimer code
« Reply #7 on: September 29, 2020, 03:45:53 pm »
Thank you Martin, that makes sense now.

TD

Bart

  • Hero Member
  • *****
  • Posts: 3952
    • Bart en Mariska's Webstek
Re: Wiki TTimer code
« Reply #8 on: September 29, 2020, 06:44:29 pm »
IMHO, the wiki could be better, by giving the complete code of the unit, rather than a puzzle on how to put it together.

If you follow the steps on the wiki page, you get a working program.
It also states where you have to declare "Start".

Bart

Handoko

  • Hero Member
  • *****
  • Posts: 3868
  • My goal: build my own game engine using Lazarus
Re: Wiki TTimer code
« Reply #9 on: September 29, 2020, 07:58:06 pm »
IMHO, the wiki could be better, by giving the complete code of the unit, rather than a puzzle on how to put it together.

I recommend this simple animation, just 58 LOC:
https://forum.lazarus.freepascal.org/index.php/topic,39790.msg274096.html#msg274096

 

TinyPortal © 2005-2018