12

这可能是一个愚蠢的问题,但我的大脑已经足够成熟了,我想我将使用我的一条“生命线”来看看我是否可以从我的堆栈溢出朋友那里获得一些帮助。;)

我需要在我的主窗体上删除所有出现的特定组件类型(其中一些在面板或标签页内,但都在同一个窗体上并由同一个窗体拥有)。这是我现在拥有的:

for i := 0 to frmMain.ComponentCount - 1 do  
  begin  
    if frmMain.Components[i] is TMyClass then frmMain.Components[i].Destroy;  
  end;    

问题是(我在编译它之前就知道会这样)一旦我销毁组件,表单的组件列表会重新索引,最终会超出范围。

解决这个问题的最佳方法是什么?我考虑过将“找到”的组件添加到一个独立的数组中,然后在这个循环之后通过它来删除它们,我认为这会起作用....但这是最好的方法吗?

TIA


更新:

你们真棒。谢谢。:)

4

6 回答 6

28

你几乎是对的。你的循环应该看起来像

for i := frmMain.ComponentCount - 1 downto 0 do
begin
  if frmMain.Components[i] is TMyClass then
    frmMain.Components[i].Free;
end;

这样,对函数“frmMain.ComponentCount”的调用在开始时就完成了,而不是再次完成。

你也应该像上面那样调用 Free,而不是 Destroy——我现在不记得为什么了。布里

于 2009-02-11T23:08:45.687 回答
10

从顶部开始并向后工作。

即:

for i := frmMain.ComponentCount - 1 downto 0 do
begin
  if frmMain.Components[i] is TMyClass then frmMain.Components[i].Free;
end; 

调用免费而不是销毁。在检查有效参考后免费调用销毁。

于 2009-02-11T23:01:36.187 回答
2

在您的情况下可能不会发生这种情况,但if frmMain.Components[i] is TMyClass检查也将为TMyClass. 如果你真的想删除一个特定的类,你可能需要添加一个额外的ClassName.

于 2009-02-12T12:59:38.590 回答
1

带有while循环的相同解决方案:

i := 0;
while i < frmMain.ComponentCount do
begin
  if frmMain.Components[i] is TMyClass then
    frmMain.Components[i].Free 
  else
    inc(i);
end;
于 2009-02-12T08:26:29.010 回答
-2

对于表单或面板中的 Fine Contrle 可以使用此代码

var

 i:Integer;

begin

for i := 0 to Panel1.ControlCount - 1 do

  begin

    if Panel1.Controls[i] is TEdit then
       Tedit(Panel1.Controls[i]).text := '';

  end;
于 2014-12-23T22:33:36.693 回答
-3

如果您需要检查和销毁命名的已知组件,请使用

If YourComponent <> Nil Then
  YourComponent.Free;
于 2010-02-03T22:43:12.637 回答