Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

Author Topic: How to access and set properties of Labels dynamically  (Read 1300 times)

andyf97

• New Member
• Posts: 19
Re: How to access and set properties of Labels dynamically
« Reply #15 on: March 31, 2023, 10:31:19 pm »

It is really interesting KodeZwerg

Would you mind explaining a bit what is actually going on with the second line of this:

Code: Pascal  [Select][+][-]
1.       if (Pos('Form1', Application.Components[x].Name) > 0) then  // This is searching the application for Form1, there are two forms.
2.         for y := 0 to Pred((Application.Components[x] as TForm).ComponentCount) do
3.

I really cannot understand the use of Pred or why it would be needed. Is is like a pointer that has past Form1 so its required to go backwards ie minus one in the results? Its confusing me because the first line is searching for one form so the results would only be one, or I am barking totally up the wrong tree?

The next one I don't follow is the relationship of the array and the label changes.

Code: Pascal  [Select][+][-]
1.       // pick one random and rename the caption to an integer
2.       x := Random(Length(arr));
3.       arr[x].Caption := IntToStr(Succ(x));
4.

I get the idea that the array will hold a list of labels and changing its caption in the array ( is the array holding the entire properties for the component or it is use more like a pointer to the real label), but how does that change the real component, surely it would require some form of update the component with the new caption.

Seeing new things with your code even this Succ I need now look it up :-)

Blaazen

• Hero Member
• Posts: 3234
• POKE 54296,15
Re: How to access and set properties of Labels dynamically
« Reply #16 on: March 31, 2023, 10:39:37 pm »
Code: Pascal  [Select][+][-]
1. for y := 0 to Pred((Application.Components[x] as TForm).ComponentCount) do

It is moreless the same as
Code: Pascal  [Select][+][-]
1. for y := 0 to (Application.Components[x] as TForm).ComponentCount-1 do

https://www.freepascal.org/docs-html/rtl/system/pred.html

So the loop var y will not go out of bounds.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

KodeZwerg

• Hero Member
• Posts: 1401
Re: How to access and set properties of Labels dynamically
« Reply #17 on: March 31, 2023, 11:08:02 pm »
Would you mind explaining a bit what is actually going on...
I'd thought I've already comment all enough but I can try to do more ...
Code: Pascal  [Select][+][-]
1. procedure TForm2.Button1Click(Sender: TObject);
2. // here I do create a new type that I need to store found TLabel object in
3. type
4.   TLabels = array of TLabel;
5. var
6.   // x, y, z are needed as Counters (x = a Form, y = an Object, z = array entries)
7.   x, y, z: Integer;
8.   // this is the actual array that holds the found objects of type TLabel
9.   arr: TLabels;
10. begin
11.   // initialize empty array
12.   arr := nil;
13.   SetLength(arr, 0);
14.   // x is my counter for the root of everything, my Pred() can also be written like
15.   //  for x := 0 to Application.ComponentCount -1 do       ...but I do hate to write -1 or +1
16.   for x := 0 to Pred(Application.ComponentCount) do
17.     // Application.Components[x] is the current object I am into, in that case I want to dig deeper into a TForm what has inside its name "Form1" written (case sensitive!)
18.     if (Pos('Form1', Application.Components[x].Name) > 0) then
19.       // y is now the root of the found form where I am digging and digging
20.       // again using Pred to avoid writing "-1"
21.       // translated this line means:
22.       //  for y := 0 to Form1.ComponentCount -1 do
23.       // but with this kind of technique we have to write it like that:
24.       for y := 0 to Pred((Application.Components[x] as TForm).ComponentCount) do
25.         // remember, x = Form1 and y = all objects on that
26.         // next line eliminate everything that is not a TLabel
27.         if (((Application.Components[x] as TForm).Components[y] is TLabel) and
28.             // and only keep a TLabel when it's Tag value is "666"
29.             (((Application.Components[x] as TForm).Components[y] as TLabel).Tag = 666)) then
30.           begin
31.             // z keeps track of my array, it represent current amount of entries
32.             // so first get current number of entries:
33.             z := Length(arr);
34.             // increase the array by one
35.             // you can also write:
36.             // SetLength(arr, z + 1);
37.             // but as told, I do hate write -1 or +1
38.             SetLength(arr, Succ(z));
39.             // here we add the found TLabel into my array
40.             // remember, x = Form1, y = the object
41.             arr[z] := ((Application.Components[x] as TForm).Components[y] as TLabel);
42.           end;
43.   // when my array is bigger than 0
44.   if (Length(arr) > 0) then
45.     begin
46.       // generate a random number based on the number of possible entries
47.       x := Random(Length(arr));
48.       // patch/overwrite the caption for one of the found possible TLabels
49.       arr[x].Caption := IntToStr(Succ(x));
50.       // the following is not needed, but I do it anyway
51.       SetLength(arr, 0);
52.       arr := nil;
53.     end;
54. end;
55.
I hope I was able to explain everything deep enough?
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

tetrastes

• Sr. Member
• Posts: 380
Re: How to access and set properties of Labels dynamically
« Reply #18 on: April 01, 2023, 11:07:09 pm »
BUT: When the project gets bigger and bigger and more and more units are added the interdependence of the units becomes very complicated and there is a chance that such a solution will not compile any more.

No, if you place uses UnitX only in implementation section.

Quote
Also, you cannot test the project units independently - you always need Form1 if you want to test Form2 (and if Form1 uses other forms and units you will also need those - a huge mess!). Another issue is that unit2 compiles only when the instance of TForm1 is really named "Form1".

And what? You also need Form2 to test Form1... etc. And your unit1 also compiles only when the instance of TForm2 is really named "Form2". What is the issue with that?

Quote
Therefore, unless you have a very simple project you should always avoid such a situation.

You didn't convince me. But, of course, I do not urge you to use my solution at all.

tetrastes

• Sr. Member
• Posts: 380
Re: How to access and set properties of Labels dynamically
« Reply #19 on: April 01, 2023, 11:17:46 pm »
Therefore, unless you have a very simple project you should always avoid such a situation.
I second that, to me it is very bad code design as it may lead to future bugs.

At least it doesn't violate KISS principle. And what are "future bugs" it may lead to?

Of course, you may consider crawling through application components to be good design for this small task.