Recent

Author Topic: Dynamic access to label names ?  (Read 4711 times)

J-G

  • Hero Member
  • *****
  • Posts: 953
Dynamic access to label names ?
« on: July 11, 2017, 12:00:02 am »
I doubt that this is possible but I've been wrong in my assumptions before !

I have a number of Labels which I want to display data in via their 'Caption' property. I could give them all unique names but it seems more efficient to retain their auto-generated name with the number   ie. Label23, Label24 etc.

What I would like to do is reference the property by dynamically creating the name through concatenation of the string 'Label' and the string of the number, in the form of  LabName :=  'Label'+IntToStr(23) (say) but of course the compiler can't resolve LabName.caption.

Maybe I shouldn't be using a TLable but I don't see a better alternative. Perhaps someone can point me to a sensible solution.
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Dynamic access to label names ?
« Reply #2 on: July 11, 2017, 12:26:42 am »
There are various ways to accomplish this. Here's one. Double-click on the empty form in a new Lazarus project and complete the FormCreate as follows.
You can style TLabelID according to your needs.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Graphics, StdCtrls, typinfo;
  9.  
  10. type
  11.   TLabelID = (labelTop, labelMiddle, labelBottom);
  12.  
  13.   TLabelArray = array[TLabelID] of TLabel;
  14.  
  15. type
  16.  
  17.   { TForm1 }
  18.  
  19.   TForm1 = class(TForm)
  20.     procedure FormCreate(Sender: TObject);
  21.   private
  22.     FLabelArray: TLabelArray;
  23.     procedure LabelClick(Sender: TObject);
  24.   public
  25.  
  26.   end;
  27.  
  28. var
  29.   Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. procedure TForm1.FormCreate(Sender: TObject);
  38. var
  39.   lid: TLabelID;
  40. begin
  41.   for lid in TLabelID do begin
  42.     FLabelArray[lid]:=TLabel.Create(Self);
  43.     with FLabelArray[lid] do begin
  44.       Top:=10 + Ord(lid)*30;
  45.       Left:=10 + Ord(lid)*30;
  46.       Caption:=GetEnumName(TypeInfo(TLabelID), Ord(lid));
  47.       OnClick:=@LabelClick;
  48.       Parent:=Self;
  49.     end;
  50.   end;
  51. end;
  52.  
  53. procedure TForm1.LabelClick(Sender: TObject);
  54. var
  55.   lbl: TLabel absolute Sender;
  56. begin
  57.   if (Sender is TLabel) then begin
  58.     lbl.Caption:='You clicked me';
  59.     lbl.Font.Color:=clRed;
  60.   end;
  61. end;
  62.  
  63. end.

Eugene Loza

  • Hero Member
  • *****
  • Posts: 674
    • My games in Pascal
Re: Dynamic access to label names ?
« Reply #3 on: July 11, 2017, 07:51:16 am »
Or if you prefer to design your form by hand (not dynamically) you may need to make and additional procedure:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate;
  2. begin
  3.   FLabelArray[labelTop] := label12;
  4.   FLabelArray[labelMiddle] := label23;
  5.   FLabelArray[labelBottom] := label53;
  6. end;
  7.  
or a bit more "flat"
Code: Pascal  [Select][+][-]
  1.  var FLabelArray = array [1..53] of TLabel;
  2.  
  3. procedure TForm1.FormCreate;
  4. begin
  5.   FLabelArray[12] := label12;
  6.   FLabelArray[23] := label23;
  7.   FLabelArray[53] := label53;
  8. end;
  9.  
and then go on with howardpc's method.
My FOSS games in FreePascal&CastleGameEngine: https://decoherence.itch.io/ (Sources: https://gitlab.com/EugeneLoza)

J-G

  • Hero Member
  • *****
  • Posts: 953
Re: Dynamic access to label names ?
« Reply #4 on: July 11, 2017, 11:09:44 am »
Thanks for all the input - specifically to Bazzao for his PM.

As I anticipated, the 'solutions' provided (IMHO) don't really make the problem go away. Each label still has to be statically addressed (unless I'm missing something).

To explain a little further, I have data amassed over the past 11 years and will continue to grow with time. My project will record events - which are sporadic - and my initial thought was to have each year's data displayed for ease of comparison. The 'problem' was how to handle a new year without having to re-visit the project and add a new set of TLabels and then re-compile the 'new' program.

I now consider this to be a 'silly' approach and (for year-on-year comparison) a graph would be vastly superior. I'll still display annual data - probably two sets (this year - last year) - which will need a manageable 14 static labels rather than 77 (increasing).

This will still allow me to display historic data in numeric form with [back] and [forward] buttons and new years are easily handled with a dynamic array of records.

If it were possible to concatenate a name with the string of a number AND the compiler could resolve the result, maybe that would make dynamic label naming a possibility but I don't think it would benefit my current project.
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Dynamic access to label names ?
« Reply #5 on: July 11, 2017, 11:50:11 am »
Each label still has to be statically addressed (unless I'm missing something).
Yes, big time, you missed RTTI.... <second sigh of today>
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Dynamic access to label names ?
« Reply #6 on: July 11, 2017, 12:48:16 pm »
I have a number of Labels ...
What I would like to do is reference the property by dynamically creating the name...

I did not understand from this that you have a variable number of labels which you want created dynamically in such a way that the user can identify each one at runtime.

Some adaptation of the attached project may suit. It adapts the number of labels shown according to how many years have elapsed since some arbitrary date. So if you were to run the example in 2018 you would get an additional 2018 label beyond all the year labels you see this year.
« Last Edit: July 11, 2017, 01:09:32 pm by howardpc »

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Dynamic access to label names ?
« Reply #7 on: July 11, 2017, 01:55:49 pm »
I did not understand the variable part either...
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

J-G

  • Hero Member
  • *****
  • Posts: 953
Re: Dynamic access to label names ?
« Reply #8 on: July 11, 2017, 03:15:06 pm »
I have a number of Labels ...
What I would like to do is reference the property by dynamically creating the name...

I did not understand from this that you have a variable number of labels which you want created dynamically in such a way that the user can identify each one at runtime.

Apologies Howard (& Thaddy) - it seems I am inept at explaining my problems - probably because I don't actually know what my problem really is.

I've moved on from the concept that started my question  --  but I have downloaded your project and will look at it shortly. It may well prove useful to the other three forum members who downloaded it before I knew that you had responded again, so I take comfort in the fact that others may benefit and your efforts are not wasted  :)
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Re: Dynamic access to label names ?
« Reply #9 on: July 12, 2017, 11:14:04 am »
As I anticipated, the 'solutions' provided (IMHO) don't really make the problem go away. Each label still has to be statically addressed (unless I'm missing something).
Have you really looked at the links I have provided? There is an example that iterates through all page components (which can be easily changed to all form components) to find the ones that we are interested in, and there is an example that iterates through all components to find ones we are interested in based on component name (with numeric index sufix). In both cases code stays the same no matter if you add or remove several components later. I do not see anything statical with this approach.
« Last Edit: July 12, 2017, 11:16:11 am by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

 

TinyPortal © 2005-2018