【问题标题】:Delphi: refer to a component from multiple framesDelphi:从多个框架中引用一个组件
【发布时间】:2016-10-27 22:09:17
【问题描述】:

我想引用一个存在于多个框架中的组件(使用循环)。所有框架的组件都相同。

  • 我有一个名为“comboBoxAccount”的组合框。
  • 我也有多个帧(我在运行时实例化)。 我创建的框架命名为:

    frm1、frm2、frm3

  • 每个框架都有一个在运行时创建的多个 TabSheets,名为: page_1、page_2、page_3

所以,我目前正在使用: Tfrm1(FindComponent('page_'+i)).comboBoxAccount

这意味着我在循环中使用 FindComponent 和 i 来访问所有 TabSheets 中的所有 comboBoxAccount

问题是我必须使用强制转换来让 Delphi 了解我要访问哪个组件,所以我把 Tfrm1( ) 放在了 FindComponent 前面。

那么,如果我想在循环中使用强制转换,我该怎么办?

我可以使用:

Tfrm1(FindComponent('page_'+i)).comboBoxAccount
Tfrm2(FindComponent('page_'+i)).comboBoxAccount
Tfrm3(FindComponent('page_'+i)).comboBoxAccount

但是有没有一种方法可以循环Tfrm 而无需一一编写?

【问题讨论】:

  • 请出示您的实际可编译代码
  • 这里涉及到我的问题的部分太多了,需要很多行代码。我的主要问题是:有没有办法从运行时实例化的框架中访问控件?有 TabSheets,对于每个 TabSheets,都有多个 TabSheets(在运行时创建),并且在每个子 TabSheet 内部都有一个带有我要访问的控件的框架。我可以使用标签吗?或者以任何方式访问控件的控件(TabSheets 内的 Tabsheets)?
  • 好的。那就不要给我们任何上下文。但不要指望主题帮助。
  • 不是我不想给出我的代码,我只是要以一种可以理解的方式重写它,所以这需要一些时间。也许今天我会完成它。放置 350 多行代码会更好吗?因为如果我不重写它并只把函数放在这里,我的朋友会花费这么多的代码行..
  • 阅读此minimal reproducible example。就我个人而言,我永远不会调用 FindComponent。为什么不只记住需要使用的控件。把它们放在一个容器里。永远不要使用这样的不安全演员表。使用类型检查强制转换。

标签: delphi vcl


【解决方案1】:

page_1page_2 等是 TabSheets,而不是框架,但您将它们转换为框架,这是错误的。

如果每个框架上都有多个 TabSheet,并且每个 TabSheet 上都有一个 ComboBox,那么您根本不会使用 FindComponent()。您将不得不遍历父/子 Controls[] 列表,或使用 FindChildControl()

但是,如果框架是 ComboBox 的 Owner(如果在设计时将 ComboBox 添加到框架中),那么您将在框架本身上使用 FindComponent()。但是你不能有多个同名的子组件,所以每个 TabSheet 上的每个 ComboBox 都需要一个唯一的名称:

cb := TComboBox(frm1.FindComponent('comboBoxAccount_'+IntToStr(i)));

重复frm1 的每个索引,然后是frm2 的所有索引,然后是frm3

如果你的 ComboBox 真的只命名为comboBoxAccount,那么我想知道你是否真的有一个父容器,上面有多个 TabSheet,每个 TabSheet 上都有一个框架,每个框架只有一个名为 comboBoxAccount 的 ComboBox在上面。如果是这种情况,您根本不需要进行任何搜索,只需直接使用现有的对象指针即可:

cb :=  frm1.comboBoxAccount;
cb :=  frm2.comboBoxAccount;
cb :=  frm3.comboBoxAccount;

但如果你真的想使用循环,那么将帧放入一个列表中,例如:

private
    Frames: TList;

...

Frames := TList.Create;
Frames.Add(frm1);
Frames.Add(frm2);
Frames.Add(frm3);

...

for I := 0 to Frames.Count-1 do
begin
  // assuming TFrm1, TFrm2, etc do not have a common ancestor holding the ComboBox...
  cb := TComboBox(TWinControl(Frames[i]).FindComponent('comboBoxAccount'));
  ...
end;

或者使用数组:

private
  // assuming TFrm1, TFrm2, etc do not have a common ancestor holding the ComboBox...
  Frames: array[0..2] of TWinControl;

...

Frames[0] := frm1;
Frames[1] := frm2;
Frames[2] := frm3;

...

for I := Low(Frames) to High(Frames) do
begin
  cb := TComboBox(Frames[i].FindComponent('comboBoxAccount'));
  ...
end;

更新:根据您提供的新信息,您可以找到这样的 ComboBox:

cb := Tfrm1(PageControl[i].Pages[j].FindChildControl('frame_'+IntToStr(i))).comboBoxAccount;

您的while 循环正在创建多个具有相同Name 的标签页和框架,这是无效的。我建议根本不要命名它们。

while condition=true do
begin
  TabSheet := TTabSheet.Create(PageControl[i]);
  TabSheet.Caption := '';
  //TabSheet.Name:='tabesheet_'+IntToStr(i);
  TabSheet.PageControl := PageControl[i];
  TabSheet.PageControl.ActivePageIndex:=0;
  {I also create a frame for each TabSheet. In every frame there is the     ComboBox that I want to access}
  frame := Tfrm1.Create(TabSheet);
  //frame.Name:='frame_'+IntToStr(i);
  frame.Parent:=TabSheet;
end;

假设一个框架是其 TabSheet 的唯一子级,那么您可以这样做:

cb := Tfrm1(PageControl[i].Pages[j].Controls[0]).comboBoxAccount;

【讨论】:

  • 感谢您的所有建议,我的朋友。我会研究你的答案并尝试不同的事情。我将尝试将每一帧放在一个列表中并循环播放。每个组合框都在一个框架内(我把它放在设计时),所以每个组合框没有唯一的名称。有没有办法遍历表单的每个控件(孩子甚至孩子的孩子)并使用标签找到组合框。
  • @ConstantinosKarentzos 我已经在回答中提到了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 1970-01-01
相关资源
最近更新 更多