0

In an android app, in a ListBox i'm creating ListBoxItems, into each Item a reactangle and into each rectangle i'm ctreating 5 labels all this dynamically in RUN TIME, 5 labels for each Listboxitem created. The only unique property of the labels is the name who changes for each listboxitem that created. Now, i can't find a way to find a specific label to change its text property. I can find in which Listboxitem and by extension which rectangle is the Label i want ( with tag_num variable) but i cant determine the specific label to change its text.

the code of creatig the Listboxitems

         ...
         lbim := TListBoxItem.Create(ListBox1);
         lbim.Parent := ListBox1;
         lbim.TextSettings.Font.Size := 12;
         lbim.StyledSettings:= 
         [TStyledSetting.Family,TStyledSetting.Style,TStyledSetting.FontColor];
         lbim.Text :=  LJsonValue1_2.Value;
         lbim.Height := 50;
         lbim.Margins.Top := 2;
         rctg := TRectangle.Create(lbim);
         rctg.Parent := lbim;
         rctg.Align := TAlignLayout.Client;
         rctg.Stroke.Kind := TBrushKind.Solid;
         rctg.Stroke.Color := $FF51ABAE;
         rctg.Stroke.Thickness := 1;
         rctg.Tag := tag_num;
         rctg.OnClick:=QuantityClick;
         rctg.Margins.Left:=2;
         rctg.Margins.Right:=2;
         rctg.Index := -5;
         lb := TLabel.Create(rctg);
         lb.Parent := rctg;
         lb.Align := TAlignLayout.Center;
         lb.TextSettings.HorzAlign := TTextAlign.Leading;
         lb.Width := 150;
         lb.Name := 'value0_'+IntToStr(tag_num);
         lb.TextSettings.Font.Size := 12;
         lb.StyledSettings:= 
         [TStyledSetting.Family,TStyledSetting.Style,TStyledSetting.FontColor];
         lb.Margins.Right := 180;
         lb.Margins.Bottom := 35;
         lb.Text := LJsonValue1_1.Value;
         lb1 := TLabel.Create(rctg);
         lb1.Parent := rctg;
         lb1.Align := TAlignLayout.Center;
         lb1.TextSettings.HorzAlign := TTextAlign.Trailing;
         lb1.Width :=  150;
         lb1.Name := 'value1_'+IntToStr(tag_num);
         lb1.TextSettings.Font.Size := 12;
         lb1.StyledSettings:= 
         [TStyledSetting.Family,TStyledSetting.Style,TStyledSetting.FontColor];
         lb1.Margins.Bottom := 35;
         lb1.Margins.left := 180;
         lb1.Text := LJsonValue4_2.Value;
         ...
         tag_num:=tag_num+1; 

and so on... It is possible to created from 1 ListBoxItem to 15 or more.. How to change, for example the lb1 Label in 10th lIstBoxItem, its text? I find a similar problem here Search for a Label by its Caption but doesnt work for me.. Any ideas?

my search code is :

  for i := 0 to ListBox1.Items.Count - 1   do
  begin
   item := Form1.ListBox1.ListItems[i];
   if item.Components[i] is TLabel then
   begin
    if TLabel(item.Components[i]).Name = 'value1'  then
     begin
      if ed_quant1.Text = '' then
       begin
         ed_quant1.Text := '0';
         TLabel(item.Components[i]).Text :=  ed_quant1.Text;
       end
      else
       begin
         TLabel(item.Components[i]).Text :=  ed_quant1.Text;
       end;
     end;
    if TLabel(item.Components[i]).Name = 'value2' then
     begin
      if ed_quant2.Text = '' then
       begin
         ed_quant2.Text := '0';
         TLabel(item.Components[i]).Text :=  ed_quant1.Text;
       end
      else
       begin
         TLabel(item.Components[i]).Text :=  ed_quant1.Text;
       end;
     end;
    end;
   end;

i'll should mention that the search takes place in another form of where the ListBox is created.

Antonis
  • 55
  • 5
  • What did your search code (based on the link you provide) look like? Without trying it, iterating over the `Controls` of the rectangle (as the rectangle is the parent of the `TLabel`) should do the trick. – Philip J. Rayment May 16 '22 at 09:34
  • I try with Components[ ] as the link and doesnt change the text. Trying using the Controls[ ] and gives me errors also. @PhilipJ.Rayment – Antonis May 16 '22 at 10:51
  • I asked you to show your code. Although if Adriaan's answer works for you, I guess that request is redundant. If his answer does work, you should accept it. – Philip J. Rayment May 16 '22 at 13:23
  • I post the search code , still Adriaan's solution didnt work , i also remove the rctg : TRectangle and now the Labels parenting from lbim : ListBoxItems. @PhilipJ.Rayment – Antonis May 16 '22 at 14:15

2 Answers2

1

This is actually rather simple but your method seems to be a lot more complicated than it should be.

When you dynamically create a TlistboxItem and then create a TLabel and set the TLisboxItem you created as owner the label doesnt need a unique name. It will need to be unique to the Item but not globally.

Example: You cannot dynamically create 2 labels in the same item with the same names but you can use the same name in 2 different items.

Example for creating new Listbox items with labels:

// Creating New Items
  lst1.BeginUpdate;
  try
    for var I := 0 to 100 do
    begin
      // Create Listbox Item
      var
      aItem := TListBoxItem.Create(lst1);
      aItem.Parent := lst1;
      aItem.Height := 50;

      // Create label in listbox item
      var
      aLabel := TLabel.Create(aItem);
      aLabel.Parent := aItem;
      aLabel.Text := 'Test';

      // Has to be unique when the same item is parent but not anywhere
      // else so you can use the name "lblTest" over and over for each new item
      aLabel.Name := 'lblTest';
    end;
  finally
    lst1.EndUpdate;
  end;

Example for changing those dynamic labels in the listboxitems:

// Changing item labels
  lst1.BeginUpdate;
  try
    for var I := 0 to lst1.Count - 1 do
    begin
      var
      aItem := lst1.ListItems[I];

      (aItem.FindComponent('lblTest') as TLabel).Text := 'Changed';
    end;
  finally
    lst1.EndUpdate;
  end;

EDIT: Since rctg is the parent of your label you will use the following:

(rctg.FindComponent('lblTest') as TLabel).Text := 'Changed';
Adriaan
  • 806
  • 7
  • 24
1

In asking questions like this, it's best to give a simplified version of your code, as it makes it easier to understand. However, I believe that the following should be useful. (I've only tried this on Windows, not Android, but I wouldn't expect that to make a difference.)

First, your search code has a problem in that you are using the same loop variable (i) for getting two different controls. That is, when you get the first item, you're looking for the first component in that item, and in the second item, you're looking for the second component, and so on. You need separate loop variables.

That you are searching from another form should make no difference, as long as you are searching the correct list box.

I didn't try using the .Components[] property, as that can include non-control components, and you are only wanting TLabels, which are controls. However, I don't see why that shouldn't work too.

My code below does not replicate your exact search-and-replace goals, so you'll have to adapt it of course. In mine, I named the labels 'value0_'+n.ToString where n is simply the n-th label in the list item. So you'll have to adjust that accordingly.

procedure TForm1.ChangeLabels;
var Item:   TListBoxItem;
    i,j:    Integer;
    Ctrl:   TControl;
    Lbl:    TLabel absolute Ctrl;
begin
  for i:=0 to ListBox1.Count-1 do begin
    Item:=ListBox1.ListItems[i];
    for j:=0 to Item.ControlsCount-1 do begin
      Ctrl:=Item.Controls[j];
      if Ctrl is TLabel then begin
        if Lbl.Name='value0_3' then Lbl.Text:='CHANGED IT!';
        if Lbl.Name='value0_4' then Lbl.Text:='Another one!';
      end;
    end;
  end;
end;