我有几个在运行时用按钮填充的TPanel。然而,我使用下面的代码将按钮从其父面板中释放出来,有时会产生访问违规错误。
procedure TfrmTakeOrder.FreeItemButtons(buttons : array of TButton);
var
cnt,i : integer;
begin
for i := 0 to gridLayoutItems.ControlCount - 1 do
begin
buttons[i].Free;
buttons[i] := nil;
end;
end;
有更好的方法吗?请记住,其他面板也有按钮,我希望"局部"释放与其他面板不集成的按钮。
在我看来,你试图从一个面板中删除所有按钮,而该面板只包含按钮。
试试这个:
while gridLayoutItems.ControlCount > 0 do
gridLayoutItems.Controls[0].Free;
如果:
- 该面板只有按钮,并且
- 您的数组中有几个面板上的所有按钮
然后使用:
var
I: Integer;
Button: TControl;
begin
for I := GridLayoutItems.ControlCount - 1 downto 0 do
begin
Button := GridLayoutItems.Controls[I];
Button.Free;
{ Find the index of Button in the Buttons array };
{ Erase that item from the array };
end;
end;
但在这种情况下,使用Buttons的TList而不是数组要方便得多,因为这样代码就会变成:
var
I: Integer;
Button: TControl;
begin
for I := GridLayoutItems.ControlCount - 1 downto 0 do
begin
Button := GridLayoutItems.Controls[I];
Button.Free;
Buttons.Remove(Button);
end;
end;
也许最好使用Length(buttons) - 1
而不是gridLayoutItems.ControlCount - 1
,这可能会有所不同。
您必须像其他答案状态一样更正for循环的边界。还有一件事:
你是如何创建按钮的?如果您与所有者创建按钮,即
buttons [i] := TButton.Create (Panel);
则不能手动释放它们。业主负责处理。在这种情况下,只需使用
buttons [i] := TButton.Create (nil);
是。使用for i := Low(buttons) to high(Buttons) do
在Delphi的最新版本(如XE5)中,Free不再存在。我用Destroy而不是Free解决了这个问题。
如果只想从父面板释放按钮:
var i : integer
begin
i := 0;
while Panel1.ControlCount > i do
if Panel1.Controls[i] is TButton then
Panel1.Controls[i].Free
else inc(i);
end;
您可以使用此代码
for i := 0 to ComponentCount-1 do
begin
if ( Components[ i ] is TPanel ) then
(Components[ i ] as TPanel ).free;
end;