根据触发事件的组合框更新相应的标签

Update corresponding label depending on which combobox fired the event

我有一个包含 n ComboBoxesn Labels 的程序,我想根据相邻的选择更新相应的 Label ComboBoxComboBox2 将更新 Label2

我为每个 ComboBox 使用相同的事件处理程序,目前正在检查 Combobox1Combobox2 是否触发了事件处理程序。有没有办法把ComboBoxItemIndex传给程序,比如Sender.ItemIndex?这目前不是一个选项,并给出错误 'TObject' does not contain a member named 'ItemIndex'.

procedure TForm2.ComboBoxChange(Sender: TObject);
begin
  if Sender = ComboBox1 then
    Label1.Caption := ComboBox1.Items.Strings[ComboBox1.ItemIndex]
  else
    Label2.Caption := ComboBox2.Items.Strings[ComboBox2.ItemIndex];
end;

此代码具有所需的行为,但显然无法扩展。

选项 1

这是最稳健的。

让你的表单拥有私有成员

private
  FControlPairs: TArray<TPair<TComboBox, TLabel>>;
  procedure InitControlPairs;

并在创建表单时调用 InitControlPairs(在其构造函数中或在其 OnCreate 处理程序中):

procedure TForm1.InitControlPairs;
begin
  FControlPairs :=
    [
      TPair<TComboBox, TLabel>.Create(ComboBox1, Label1),
      TPair<TComboBox, TLabel>.Create(ComboBox2, Label2),
      TPair<TComboBox, TLabel>.Create(ComboBox3, Label3)
    ]
end;

您需要手动将控件添加到此数组。这是这种方法的缺点。但你只需要做一次,就在这里。然后其他一切都可以自动完成。

现在,这就是它变得非常棒的地方:让您所有的组合框共享这个 OnChange 处理程序:

procedure TForm1.ComboBoxChanged(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to High(FControlPairs) do
    if FControlPairs[i].Key = Sender then
      FControlPairs[i].Value.Caption := FControlPairs[i].Key.Text;
end;

选项 2

忘记任何私有字段。现在改为确保每一对都有唯一的 Tag。所以第一个组合框和标签都有 Tag = 1,第二对有 Tag = 2,依此类推。那么你可以简单地做

procedure TForm1.ComboBoxChanged(Sender: TObject);
var
  TargetTag: Integer;
  CB: TComboBox;
  i: Integer;
begin

  if Sender is TComboBox then
  begin

    CB := TComboBox(Sender);
    TargetTag := CB.Tag;

    for i := 0 to ControlCount - 1 do
      if (Controls[i].Tag = TargetTag) and (Controls[i] is TLabel) then
      begin
        TLabel(Controls[i]).Caption := CB.Text;
        Break;
      end;

  end;

end;

作为共享组合框事件处理程序。这里的缺点是您必须确保控制窗体上所有控件的 Tag 属性(至少与标签具有相同的父级)。此外,它们必须具有相同的父控件。

每个组件都有一个 Tag 属性 继承自 TComponent,其中 Tag 是一个指针大小的整数。因此,您可以将每个 TLabel 指针直接存储在相应的 TComboBox.Tag 中,例如:

procedure TForm2.FormCreate(Sender: TObject);
begin
  ComboBox1.Tag := NativeInt(Label1);
  ComboBox2.Tag := NativeInt(Label2);
end;

这样,ComboBoxChange()就可以直接访问修改后的TComboBoxTLabel了,eg:

procedure TForm2.ComboBoxChange(Sender: TObject);
var
  CB: TComboBox;
begin
  CB := TComboBox(Sender);
  if CB.Tag <> 0 then
    TLabel(CB.Tag).Caption := CB.Items.Strings[CB.ItemIndex];
end;