Bookstore

Recent

Author Topic: [SOLVED]Adapting this code to use TFloatSpinEdit?  (Read 2555 times)

Lampbert

  • New Member
  • *
  • Posts: 33
Re: Adapting this code to use TFloatSpinEdit?
« Reply #15 on: February 02, 2020, 09:28:30 pm »

Hi again :) - this is what my CreateTimerNormal procedure looks like now:

Code: Pascal  [Select]
  1. procedure TForm1.CreateTimerNormal;
  2. begin
  3.   NewTimer := TTimer.Create(Self);
  4.   with NewTimer do
  5.     begin
  6.       Interval := 1000;
  7.       OnTimer := @timCountdownTimer;
  8.       Enabled := False;
  9.     end;
  10.   NewTimer.Name := 't' + IntToStr(StringGrid1.RowCount);
  11.   TimerList.Add(NewTimer);
  12.   Memo1.Lines.Add('List item number ' + IntToStr(TimerList.Count) + '- ' + NewTimer.Name); // Just so I can visualize TObjectList doing its thing
  13. end;

With this at the start:

Code: Pascal  [Select]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   TimerList := TObjectList.Create;
  4. end;  

Now, in all of my other procedures, since I was only using one countdown, instead of loads, the Timer was referenced as NewTimer, but that's not the name of the timers anymore - now it's t[number]. But how do I reference them in my other procedures so that I can (end goal) have loads of them running at once and counting down in my StringGrid?

Thank you.

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: Adapting this code to use TFloatSpinEdit?
« Reply #16 on: February 03, 2020, 10:27:06 am »
I think you didn't understand what I tried to tell you. What I would do is something like:

Code: Pascal  [Select]
  1. procedure TForm1.CreateTimerForRow(const Row: Integer);
  2.  
  3.   function InRange(Index, MinIdx, MaxIdx: Integer): Boolean;
  4.   begin
  5.     Result := (Index >= MinIdx) and (Index <= MaxIdx);
  6.   end;
  7.  
  8. var
  9.   Last: Integer;
  10. begin
  11.   { Make sure there is a place for the timer }
  12.   Last := TimerList.Count - 1;
  13.   if not InRange(Row, 0, Last) then
  14.     while TimerList < Last do
  15.       TimerList.Add(Nil);
  16.   { Murphy-guard: shouldn't happen (much) }
  17.   if Assigned(TimerList.Items[Row]) then
  18.     TimerList.Items[Row].Free;
  19.  
  20.   { Now set the new timer in its proper place }
  21.   TTimer(TimerList.Items[Row]) := TTimer.Create(Self);
  22.   NewTimer := TTimer(TimerList.Items[Row]);
  23.   with NewTimer do begin
  24.     Interval := 1000;
  25.     OnTimer := @timCountdownTimer;
  26.     Enabled := False;
  27.   end;
  28. end;

From then on you can refer to the timer corresponding to any grid row just by doing:
NewTimer := TTimer(TimerList.Items[Row]);
(as we did above) which will allow you to implement, for example, a popup menu for the grid with items to stop/restart/modify the timer corresponding to, say, the selected row.

Now we come to one small problem: Since all your timers are calling the same OnTimer handler, how do you know which timer is it and to which grid row it is assocciated? For that we can now use safely your previous suggestion of using the timer's Tag property, which is as simple as modyfing part of the previous code to look like:

Code: Pascal  [Select]
  1. function TForm1.CreateTimerForRow(const Row: Integer): Integer;
  2.  
  3.   { function InRange() }
  4.  
  5. var
  6.   Last: Integer;
  7. begin
  8.   {
  9.   ... Code to make place for the timer ...
  10.   }
  11.  
  12.   { Now set the new timer in its proper place }
  13.   TTimer(TimerList.Items[Row]) := TTimer.Create(Self);
  14.   NewTimer := TTimer(TimerList.Items[Row]);
  15.   with NewTimer do begin
  16.     Interval := 1000;
  17.     OnTimer := @timCountdownTimer;
  18.     Enabled := False;
  19.     Tag := Row;
  20.   end;
  21. end;

The handler timCountdownTimer() (as taken from my previous full example) should then be something like:

Code: Pascal  [Select]
  1. procedure TForm1.timCountdownTimer(Sender: TObject);
  2. var
  3.   ATimer: TTimer;
  4. begin
  5.   ATimer := Sender as TTimer;
  6.   StringGrid1.Cells[ColumNo, ATimer.Tag] := SecsToHmsStr(SecondsBetween(Now, TimeOut));;
  7.   if Now > Timeout then ATimer.Enabled := False;
  8. end;

As always, this all is just a Q&D example of how it could be done; adapt and expand to your heart's content! :)

HTH!
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Lampbert

  • New Member
  • *
  • Posts: 33
Re: Adapting this code to use TFloatSpinEdit?
« Reply #17 on: February 23, 2020, 03:13:14 pm »
Thank you very much for the code, but I've still been running into great difficulty trying to get this code to work - I get loads of errors that I do not know how to fix. Do you still have the project on your end that you could send this to me?

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: Adapting this code to use TFloatSpinEdit?
« Reply #18 on: February 23, 2020, 04:33:36 pm »
No, sorry; I write those small examples on-the-fly and almost never store them unless there is a whole program project behind them.

Maybe it would be better if you sent your project so that I could see what errors it gives and why and how they could be solved? I don't have much time now but I may be able to give it a look this night or tomorrow.

Alternatively I could write a full multi-alarm project (which would come in handy as I'm about to expand my little "clock" program ;)) but that will take quite some more time.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Lampbert

  • New Member
  • *
  • Posts: 33
Re: Adapting this code to use TFloatSpinEdit?
« Reply #19 on: February 23, 2020, 05:00:23 pm »
Thank you very much! Attached is the project with the two errors.

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: Adapting this code to use TFloatSpinEdit?
« Reply #20 on: February 23, 2020, 05:08:45 pm »
Got it, thanks. I'm about to go out for a few hours but, gods willing, I'll give it a whirl this night or early tomorrow. :)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Lampbert

  • New Member
  • *
  • Posts: 33
Re: Adapting this code to use TFloatSpinEdit?
« Reply #21 on: February 23, 2020, 05:38:00 pm »
Thanks very much!

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: Adapting this code to use TFloatSpinEdit?
« Reply #22 on: February 24, 2020, 02:36:12 pm »
So you don't think I've forgotten you ...  ;)

About the two errors, they are mine and quite obvious :-[

The first is in:
Code: Pascal  [Select]
  1.   { Make sure there is a place for the timer }
  2.   Last := TimerList.Count - 1;
  3.   if not InRange(Row, 0, Last) then
  4.     while (TimerList < Last) do // Overloaded operator
  5.       TimerList.Add(Nil);

Since TimerList is a TObjectList and Last an Integer and doen't exist an operator to compare them they are, of course, incompatible types!

The intention of that piece of code is to grow TimerList so that we can safely set/acess TimerList[Row], so the code should have been (doing away with Last):
Code: Pascal  [Select]
  1.   { Make sure there is a place for the timer }
  2.   while not InRange(Row, 0, TimerList.Count) do
  3.     TimerList.Add(Nil);
but that's not needed at all; we can just simply do:
Code: Pascal  [Select]
  1.   { Make sure there is a place for the timer }
  2.   if not InRange(Row, 0, TimerList.Count) then
  3.     TimerList.Capacity := Row + 1;


The second error, though a bit more subtle is equally stupid:
Code: Pascal  [Select]
  1.   { Now set the new timer in its proper place }
  2.   TTimer(TimerList.Items[Row]) := TTimer.Create(Self); // Arg cannot be assigned to
  3.   NewTimer := TTimer(TimerList.Items[Row]);
  4.   with NewTimer do begin
  5.     {... set timer properties ...}
  6.   end;

Well, of course! What a bad day I had, hadn't I? That should be replaced by:
Code: Pascal  [Select]
  1.   { Now set the new timer in its proper place }
  2.   NewTimer := TTimer.Create(Self);
  3.   with NewTimer do begin
  4.     {... set timer properties ...}
  5.   end;
  6.   TTimer(TimerList.Items[Row]) := NewTimer;


On another note, your code (if you excuse me saying so) is something of a mess (though that is probably because it's still in development, isn't it?) so I decided to start almost from scratch and build a fully working example. It'll take a little, cause I've a pretty busy day but since I started last night and it's almost complete I hope it'll be ready late this afternoon or early evening, including a text explaining (more or less) what it does, how and why it is the way it is (i.e. my reasoning for making things one way and not another).

See you later :)
« Last Edit: February 24, 2020, 02:53:50 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Lampbert

  • New Member
  • *
  • Posts: 33
Re: Adapting this code to use TFloatSpinEdit?
« Reply #23 on: February 26, 2020, 11:51:34 am »
Thank you very much for your time lucamar! The code works just as I want it to now and, thanks to you, I can proceed with the aspects of my project that I understand.

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: Adapting this code to use TFloatSpinEdit?
« Reply #24 on: February 26, 2020, 09:16:55 pm »
Thank you very much for your time lucamar! The code works just as I want it to now and, thanks to you, I can proceed with the aspects of my project that I understand.

OK, glad it works!

I've been a little busy but now I can (finally!) upload a full demo project including a rather long README (which cost me the lion's share of the time dedicated to this project) with most of the thinking that went on to it.

In it I changed some of the things posted before so maybe you'll want to give a look.

Anyway, it might be useful for some other people looking for similar answers to their questions so here it is, in all its (scarce) glory: the final "timers demo" (attached).

Have fun!  ;D


ETA:

Some small bugs managed to nest in the project. Very annoying. Re-attached a corrected version.
« Last Edit: February 27, 2020, 09:54:56 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Lampbert

  • New Member
  • *
  • Posts: 33
Re: [SOLVED]Adapting this code to use TFloatSpinEdit?
« Reply #25 on: February 27, 2020, 01:03:05 am »
Thanks lucamar - I've just been reading your project and it's beautifully written (both formatting and logic) - I will definitely learn from this. Do you have other projects published that I could read (in Object Pascal)? Thanks!

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: [SOLVED]Adapting this code to use TFloatSpinEdit?
« Reply #26 on: February 27, 2020, 11:09:49 am »
Thanks lucamar - I've just been reading your project and it's beautifully written (both formatting and logic) - I will definitely learn from this.

Thanks, that is what I always hope, that the little I do be of help to others. :)

Quote
Do you have other projects published that I could read (in Object Pascal)?

Not at the moment. I had some (Delphi ones) in Google Code but I I deleted them when they closed the service and didn't bother to move them to another service. I'm thinking of starting to publish again and building a web site with tutorial content but I'm very busy with other things and have very little free-time :(
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.