我试图在关闭表单时释放一个组件,但是当我运行此代码时,我不断收到“无效的类类型转换”错误,我不知道为什么。
procedure TfrmMenu.FormHide(Sender: TObject);
var
I: Integer;
sID: String;
begin
I := 0;
repeat
Inc(I);
with dmMenu.qryMcDonalds do
begin
SQL.Text := 'Select ItemID FROM tblMenu WHERE ItemID LIKE "' + IntToStr
(I) + '%"';
Open;
end;
sID := dmMenu.qryMcDonalds.Fields[0].AsString;
if (Components[I] as TImage).Name = 'imgd' + sID then
begin (Components[I] as TImage)
.Free;
end;
if (Components[I] as TLabel).Name = 'lbld' + sID then
begin (Components[I] as TLabel)
.Free;
end;
until I = ComponentCount - 1;
end;
最佳答案
你的问题在这部分:
if (Components[I] as TImage).Name = 'imgd' + sID then
begin (Components[I] as TImage)
.Free;
end;
if (Components[I] as TLabel).Name = 'lbld' + sID then
begin (Components[I] as TLabel)
.Free;
end;
Delphi 中的 as
转换基本上是一个断言转换:您是说您确定它将是那种类型,如果不是,则引发无效的转换异常。现在,您断言每个组件都将同时是 TImage
和 TLabel
,这显然永远不会成立。你可能真正想做的是:
if (Components[I] is TImage) and (Components[I].Name = 'imgd' + sID) then
begin
Components[I].Free;
end;
if (Components[I] is TLabel) and (Components[I].Name = 'lbld' + sID) then
begin
Components[I].Free;
end;
你实际上并不需要那里的类型转换,因为 Name
是 a property on the TComponent
base class.编辑: Andreas 在评论中指出的几点:
首先,如果您要迭代一个集合并从中删除项目,则需要向后工作。为了说明原因,让我们从此列表中删除所有偶数:
[1, 3, 5, 2, 4, 6]
所以如果我们做这样的事情:for i := 0 to list.Length - 1 do
begin
if list[i] mod 2 = 0 then
begin
list.Remove(i);
end;
end;
在前 3 次迭代中,我们发现不是偶数的数字。到现在为止还挺好。但是在#4 (i = 3) 上,我们有一个偶数。我们将其从列表中删除。该列表现在是 [1, 3, 5, 4, 6]
。现在我们将 i
增加到 4。这个新列表中的元素 #4 是 6;我们已经跳过了 4!这仅在您向后计数时才有效,因为删除内容只会重新安排您已经完成的工作,而不是您还剩下要做的工作。此外,表单上的
Components
集合将包含您的所有组件,无论它们在表单设计器中的设置顺序如何。您称为 imgd1
的任何图像都不太可能成为该集合中的组件 #1。如果您正在寻找名称以 imgd
或 lbld
开头后跟数字的这些类型的任何组件,您可能需要编写一个自定义名称验证函数来检查它。但是检查数字是否与 I
相同或多或少没有用,因为 I
在这里完全是任意的。关于delphi - 我不断收到 "Invalid class typecast"错误,我不知道为什么,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62521608/