-2

So I need to locate some dynamicly created TLabel components on my form, and change the caption for them but I must be doing something wrong. Please check the code bellow and help me out, I just don't know what else to try:

procedure TmainForm.setLabelCaptionForPanel(pan:TPanel; ordin: integer);
var
  j:integer;
begin
    for j := 0 to mainform.ComponentCount - 1 do
    begin
      if mainform.Components[j] is TLabel then
      if StartsText('Layernumber',mainform.Components[j].Name) then
      begin
        if mainform.Components[j].GetParentComponent = pan then
          begin
            (Mainform.Components[j] as TLabel).Caption := IntToStr(ordin);
          end;
      end;
    end;
end;

I simply do not understand the problem If I simply try this code:

lbx:=TLabel.Create(self);
lbx:=FindComponent('Layernumber1') as TLabel;
lbx.Caption:='jkjkghgkjghk';

It works like a charm... So what am I doing wrong ?

Please...

EDIT

I added the memo lines to the code so:

procedure TmainForm.setLabelCaptionForPanel(pan:TPanel; ordin: integer);
var
  j:integer;
  lbx:TLabel;
begin
memo1.lines.Add('Setting layer lbl caption on panel:'+pan.name+', to:'+IntToStr(ordin));
//lbx:=TLabel.Create(self);
//lbx:=FindComponent(vt.FieldValues['Layernumber']+) as TLabel;
    for j := 0 to ComponentCount - 1 do
    begin
      if Components[j] is TLabel then
      if StartsText('Layernumber',Components[j].Name) then
      begin
        Memo1.Lines.Add('Component label found:'+mainform.Components[j].Name);
        Memo1.Lines.Add('Having parent:'+TLabel(Mainform.Components[j]).Parent.Name);
        if Components[j].GetParentComponent = pan then
          begin
            Memo1.Lines.Add('Labem found (name):'+Components[j].Name+' with caption:'+TLabel(Components[j]).Caption);
            Memo1.Lines.Add('Has parent:'+pan.Name);
//            Memo1.Lines.Add('xxx...:'+TLabel(Mainform.Components[j]).name+' - '+TLabel(Mainform.Components[j]).Caption+' -> '+IntToStr(ordin));
            (Components[j] as TLabel).Caption := IntToStr(ordin);
            Memo1.Lines.Add('Done');
          end;
      end;
    end;
end;

I run the procedure in an OnMouseUp event of a panel And my memo looks like this when running:

Senderul:Layeru0
Searching on panel:Layeru0
Panelul:Layeru0 - cu captionul obtinut=0
GetNumar de layere=3
Layer panel gasit este:Layeru3
Setting layer lbl caption on panel:Layeru3, to:3
Component label found:Layernumber0
Having parent:Layeru0
Component label found:Layernumber1
Having parent:Layeru1
Component label found:Layernumber2
Having parent:Layeru2
Component label found:Layernumber3
Having parent:Layeru3
Labem found (name):Layernumber3 with caption:3
Has parent:Layeru3
Done
Layer panel gasit este:Layeru0
Setting layer lbl caption on panel:Layeru0, to:2
Component label found:Layernumber0
Having parent:Layeru0
Labem found (name):Layernumber0 with caption:0
Has parent:Layeru0
Done
Component label found:Layernumber1
Having parent:Layeru1
Component label found:Layernumber2
Having parent:Layeru2
Component label found:Layernumber3
Having parent:Layeru3
Layer panel gasit este:Layeru2
Setting layer lbl caption on panel:Layeru2, to:1
Component label found:Layernumber0
Having parent:Layeru0
Component label found:Layernumber1
Having parent:Layeru1
Component label found:Layernumber2
Having parent:Layeru2
Labem found (name):Layernumber2 with caption:2
Has parent:Layeru2
Done
Component label found:Layernumber3
Having parent:Layeru3
Layer panel gasit este:Layeru1
Setting layer lbl caption on panel:Layeru1, to:0
Component label found:Layernumber0
Having parent:Layeru0
Component label found:Layernumber1
Having parent:Layeru1
Labem found (name):Layernumber1 with caption:1
Has parent:Layeru1
Done
Component label found:Layernumber2
Having parent:Layeru2
Component label found:Layernumber3
Having parent:Layeru3

As you may see the 'Done' line says the code is executing

user1137313
  • 2,390
  • 9
  • 44
  • 91
  • Please show full code, including how you "dynamicly created TLabel components". Or debug your code yourself. – kludg Jan 20 '15 at 15:43
  • The second code block of your original post makes no sense. First, you create a TLabel and assign it to Lbx. In the next line you assign a different component to this Lbx and there you lose contact with the label you just created. Do you at any point assign a parent to the label? Otherwise the label just doesn't show up at all. – Tom Brunberg Jan 20 '15 at 16:07
  • 1
    Why are you searching for corect Label in your mainForm components list? Wouldn't it be better to search for it in Panels components list? This way you reduce the number of components that you need to iterate through and also get rid of the need to check if the Label has specific Panel for parent since you will be checking only Panels children. – SilverWarior Jan 20 '15 at 17:21
  • 1
    If a component has mainForm as an `Owner` it cannot be in a Panel's `Components` list (it is in a Panel's `Controls` list if it has the Panel as a `Parent`). – kludg Jan 20 '15 at 17:38
  • voted to close because it is impossible to understand what is wrong with the OP code. – kludg Jan 20 '15 at 18:01

2 Answers2

2
var
  i: integer;
begin
  for i := 0 to pan.ControlCount -1 do
  begin
    if (pan.Controls[i] is TLabel) and 
      (pan.Controls[i].Name = 'YOURLABEL' + IntToStr(i)) then
      TLabel(pan.Controls[i]).Caption := 'Do whatever you want';
  end;
end;
Chris Rolliston
  • 4,788
  • 1
  • 16
  • 20
oPsDCadarn
  • 106
  • 3
  • This code is wrong. A component (TLabel) cannot be both in a Form's and a Panel's `Components` list. – kludg Jan 20 '15 at 17:55
  • @ChrisRolliston it looks better now – kludg Jan 20 '15 at 18:39
  • It would be even better if there was more than just code – David Heffernan Jan 20 '15 at 18:42
  • @user246408 The code is not wrong. Obviously a component can't have 2 parents, but in YOUR case, you're looking for TLabels inside a Panel, so... don't undersant why you said the code is wrong. – oPsDCadarn Jan 20 '15 at 19:03
  • @oPsDCadarn - it **was** wrong. Now it is fixed by Chris. – kludg Jan 20 '15 at 19:06
  • Was not wrong, the diference is that earlier it was iterating in all Components of "pan", now is iterating in all controls. Anyway, this should solve your issue. – oPsDCadarn Jan 20 '15 at 19:35
  • @oPs The label is owned by the form and not the panel. So yes, the code you posted was wrong. – David Heffernan Jan 20 '15 at 19:40
  • In your code **if (...) and (pan.Controls[i].Name = 'YOURLABEL' + IntToStr(i)) then** only work if TLabel.name = "YOURLABEL0". Let's assume we have 4 panels and on each panel just one "TLabel" is generated dynamically. The names created on the panels (Panel0 to Panel3) will be named: "YOURLABEL0" to "YOURLABEL3". On Panel2 look for `Name = 'YOURLABEL0'` will not work. On each panel, there is always only **one TLabel**, so **for i := 0** will always be **i=0**. Use `if (pan.Controls[i] is TLabel) and (pos('YOURLABEL',pan.Controls[i].Name) = 1 ) then` instead. – moskito-x Jan 20 '15 at 20:16
  • Guys, my code works just fine. The problem was elsewhere in my project... where I rewrote all the captions of those panels. So stop arguing over my code, it works just fine. Of course it could be optimized (so I do not parse the whole collection of components of the form) but that is about it. And that is just optimization, not issue solving. As I said, my issue was outside the code I presented here. I am sorry for wasting your time with this. I had no idea where to look for errors because the code seemed ok, that is why I wanted another pair of eyes to check it to make sure. Thank you all – user1137313 Jan 20 '15 at 23:12
1
(Mainform.Components[j] as TLabel).Caption := IntToStr(ordin);

This will change the caption of that label control. Since you report that the code fails to change the label we can only conclude that this code is not executing, or that it is executing on the wrong label.

You could narrow the problem down by stepping through the code. First of all set a breakpoint on this line:

if StartsText('Layernumber',mainform.Components[j].Name) then

If that breakpoint does not fire then none of the components owned by mainform are of type TLabel.

Then move on to

if mainform.Components[j].GetParentComponent = pan then

If a break point there does not fire then none of the labels owned by mainform have names that start with 'Layernumber'.

And so on. You can use this technique to understand why the assignment to Caption is not executing, or why it is executing on the wrong component.

This code is of course quite horrid to read. Surely you can do better. Why create the label and then forget all about it. Make life simple for yourself by remember the reference to the label in a form variable.

FLabelNumber1 := TLabel.Create(Self);
...

Then you can throw away all the code in the question and use FLabelNumber1 directly.

To perhaps give you more encouragement, I can honestly say that in over 15 years of shipping Delphi software, I have never shipped code that called FindComponent.


As an aside, you almost certainly should not be using the mainform global variable. Your code executes in a method of TmainForm. So it already has access to the form object through the implicit Self variable. Please take the time to remove all these uses of mainform.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I added a Memo line after each line of code with values obtained in that code line, and trust me, it is working just fine, except the label caption does not get changed... What else might be the problem? – user1137313 Jan 20 '15 at 15:35
  • Also I removed the mainform from the code (it got there from before I declared the procedure as public). Still nothing changes... – user1137313 Jan 20 '15 at 15:36
  • *This will change the caption of that label control. Since you report that the code fails to change the label we can only conclude that this code is not executing, or that it is executing on the wrong label.* – David Heffernan Jan 20 '15 at 15:38
  • Since the code is executing, you must be changing the caption of the wrong label. I guess you are going to ignore my advice to remember the label reference. – David Heffernan Jan 20 '15 at 16:24
  • What do you mean 'remember the label reference'? As you can see in the memo listing above, the right Tlabel is referenced – user1137313 Jan 20 '15 at 18:38
  • I mean what I said already in the answer. When you call `TLabel.Create`, remember the reference that is returned. Then you can use it later rather than all this horrid frabbing about. As for the right label being referenced, clearly that's not the case. It you were changing the caption of the right label, then you'd see the caption change. Instead of arguing, why don't you just post a complete program and demonstrate what's wrong? – David Heffernan Jan 20 '15 at 18:41
  • I found my problem. I added a showmessage right after changing the caption, so I can see the caption right after it is changed. And it changes, but somewhere in my code I re-initialize the captions with the previous values and that is why I thought the label caption was not being changed – user1137313 Jan 20 '15 at 18:46
  • David, I will award the points to you since if it wasn't for my 'rest of the program' issue, then your answer is pretty elaborate and would have solved perhaps my problem. Btw I was not arguing, I just saw that your answer was nothing I did not check before, I am no noob, but sometimes I need a second pair of eyes to look at my problem because I am doing to many things at once and sometimes I get stuck with extremely easy issues that I can normally solve easily, but it happens to just not see them – user1137313 Jan 20 '15 at 18:51
  • What you recommended is not a solution for me,'to remember the reference', because my panels (that contain the label) are created by the user on click of a menu item, then panels can be rearranged in the form, or deleted. – user1137313 Jan 20 '15 at 18:54
  • 1
    You can use containers. I assure you that you don't need to use the name to identify the control. – David Heffernan Jan 20 '15 at 18:55
  • Now that you said that, please exemplify. With code if you can. Thank you – user1137313 Jan 20 '15 at 23:13
  • You could have a dictionary with a panel as the key and its label as the value. – David Heffernan Jan 20 '15 at 23:19