在 Delphi 的 android 应用程序中搜索在运行时创建的标签

Search for a Label which created on runtime in android app in Delphi

在一个 android 应用程序中,在一个 ListBox 中,我正在创建 ListBoxItems,在每个 Item 中有一个 reactangle,在每个矩形中,我正在 运行 TIME 中动态地处理 5 个标签,5创建的每个列表框项目的标签。标签中唯一唯一的 属性 是为创建的每个列表框项目更改的名称。现在,我找不到找到特定标签来更改其文本的方法 属性。我可以在哪个 Listboxitem 中找到哪个矩形是我想要的标签(使用 tag_num 变量),但我无法确定要更改其文本的特定标签。

创建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; 

等等... 可以从 1 个 ListBoxItem 创建到 15 个或更多。如何更改,例如第 10 个 lIstBoxItem 中的 lb1 标签,其文本? 我在这里 Search for a Label by its Caption 发现了类似的问题,但对我不起作用。有什么想法吗?

我的搜索代码是:

  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;

我应该提到搜索是在创建列表框的另一种形式中进行的。

这实际上很简单,但你的方法似乎比应该的要复杂得多。

当您动态创建 TlistboxItem,然后创建 TLabel 并将您创建的 TLisboxItem 设置为所有者时,标签不需要唯一名称。它需要对项目是唯一的,但不是全局的。

示例: 您不能在同一个项目中动态创建 2 个名称相同的标签,但可以在 2 个不同的项目中使用相同的名称。

创建带有标签的新列表框项目的示例:

// 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;

更改列表框项目中那些动态标签的示例:

// 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;

编辑: 由于 rctg 是您标签的父级,因此您将使用以下内容:

(rctg.FindComponent('lblTest') as TLabel).Text := 'Changed';

在提出这样的问题时,最好提供一个简化版本的代码,这样更容易理解。但是,我相信以下内容应该有用。 (我只在 Windows 上试过,未在 Android 上试过,但我不认为这会有所作为。)

首先,您的搜索代码存在问题,因为您使用相同的循环变量 (i) 来获取两个不同的控件。也就是说,当您获得第一个项目时,您正在寻找该项目中的第一个组件,而在第二个项目中,您正在寻找第二个组件,依此类推。您需要单独的循环变量。

只要您搜索的是正确的列表框,那么您从其他表单搜索应该没有什么区别。

我没有尝试使用 .Components[] 属性,因为它可以包含 non-control 组件,而您只需要 TLabels,它们是控件。但是,我不明白为什么这也行不通。

我下面的代码并没有完全复制您的 search-and-replace 目标,因此您当然必须对其进行调整。在我的列表中,我将标签命名为 'value0_'+n.ToString,其中 n 只是列表项中的 n-th 标签。所以你必须相应地调整它。

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;