我正在尝试在运行时生成TLabel,并使用此代码将它们插入VertScrollBox;
var
i, f: integer;
RT_Label: TLabel;
begin
f:= 10;
for i := 0 to 20 do
begin
RT_Label := TLabel.Create(Self);
RT_Label.Name := 'Label' + i.ToString;
RT_Label.Text := 'SampleLabel' + i.ToString;
RT_Label.Position.Y := f;
RT_Label.Align := TAlignLayout.Top;
RT_Label.Parent := VertScrollBox1;
inc(f, 15);
end;
end;
标签显示没有问题,但是当我尝试使用此代码释放生成的标签时:
var
i: integer;
LComponent: TComponent;
begin
for i := 0 to ComponentCount-1 do
begin
if( Components[i] is TLabel )then
if StartsText('Label', (Components[i] as TLabel).Name) then
begin
LComponent := (Components[i] as TLabel);
If Assigned(LComponent) then FreeAndNil(LComponent);
end;
end;
end;
然后,我总是收到错误'参数超出范围'。
如何在运行时正确删除添加到VertScrollBox的TLabel?
您从下面的行开始循环
for i := 0 to ComponentCount-1 do
但是,当您释放组件时,它会作为清理代码的一部分从“组件”列表中删除。因此,释放的每个组件都会将列表的大小减小1。ComponentCount-1
表达式在for循环启动时将被评估一次,因此不会进行更新以反映更改。
即使您可以解决此问题,循环也会跳过项目。也就是说,如果您删除的项目3,项目4现在将变为项目3,但您的循环将前进到项目4。
不过,解决方法很简单。简单地向后迭代列表:
for i := ComponentCount-1 downto 0 do
值得一提的是,您的代码实际上只会在Windows和OSX上释放项目。在移动设备上,编译器使用ARC,只有在删除了所有引用后,ARC才会释放该对象。解决方案/解决方法/错误[1]是调用DisposeOf
而不是组件的Free
。
此外,as
运算符已经保证对象是Assigned
,因此不需要额外的测试。无需FreeAndNil
将被重新分配到范围或直接超出范围的局部变量,并且无需在释放对象之前强制转换对象。由于Free(或DisposeOf
)方法存在于公共祖先类中,因此编译器将解析任何后代类的链接。
因此,您的代码可以简化为:
var
i: integer;
begin
for i := ComponentCount-1 downto 0 do
begin
if Components[i] is TLabel then
if StartsText('Label', (Components[i] as TLabel).Name) then
Components[i].DisposeOf;
end;
end;
[[1]-取决于您与谁交谈。