如何在运行时清除 TGridPanelLayout
How to clear a TGridPanelLayout at runtime
我的应用程序使用 TGridPanelLayout 向用户显示大量图像。当用户点击正确的图像时,所有图像都会被清除并呈现一系列新图像。将图片添加到网格的代码如下所示:
// Clear the grid of all controls, rows and columns and reinitialize
Grid.ControlCollection.Clear;
Grid.ColumnCollection.Clear;
Grid.RowCollection.Clear;
// Next follows some code to add columns and rows
// Display the names, n_images = rows * columns
for i := 0 to n_images - 1 do
begin
Image := TImage.Create (nil);
Image.HitTest := True;
if Sel_Array [i]
then Image.OnClick := test_positive
else Image.OnClick := test_negative;
c := i mod Options_Project.Cols;
r := i div Options_Project.Cols;
Image.Name := Format ('Image_%2.2d_%2.2d', [r, c]);
Image.Bitmap.LoadFromFile (Sel_Names [i]);
Image.Align := TAlignLayout.alClient;
Grid.AddObject (Image); // Grid: TGridPanelLayout
end; // for
一切正常,但问题在于重新创建 TGridPanelLayout。当第二次执行 Grid.ControlCollection.Clear
时,其中一个图像被释放时发生访问冲突。
如何在运行时清除 TGridPanellayout 而不会崩溃?还有一个问题:AddObject 是将控件添加到 TGridPanelLayout 的正确方法吗?我尝试了 AddControl 但没有显示图像。
此应用程序已在 Windows 7.
中进行测试
编辑
Tom 注意到我应该分配 .Parent 并且成功了,连同 Dalija 的评论我应该使用 AddControl。以下代码有效:
for i := 0 to n_images - 1 do
begin
Image := TImage.Create (Grid);
Image.HitTest := True;
if Sel_Array [i]
then Image.OnClick := test_positive
else Image.OnClick := test_negative;
c := i mod Options_Project.Cols;
r := i div Options_Project.Cols;
Image.Name := Format ('Image_%2.2d_%2.2d', [r, c]);
Image.Bitmap.LoadFromFile (Sel_Names [i]);
Image.Align := TAlignLayout.alClient;
Image.Parent := Grid;
Grid.ControlCollection.AddControl (Image);
end; // for
谢谢大家的帮助!
调用Grid.ControlCollection.Clear删除集合中的项目是正确的。来自帮助:
Clear empties the Items array and destroys each TCollectionItem.
请注意 "destroys",这意味着它拥有管理图像生命周期的所有权和责任。
你说:
an access violation occurs when one of the images is freed.
你的意思是通过你的代码主动释放?那就是错了,AV的原因。
图片是否与用户点击并触发显示一系列新图片的图片相同?然后您需要查看代码如何在 test_positive 中操作图像,也许还有 test_negative。
要向 TGridPanelLayout 添加控件,您可以使用
Grid.AddObject(Image);
或
Image.Parent := Grid;
Grid.Controls.Add(Image);
注意,在这种情况下,您需要设置父级才能显示图像(并由网格管理)。
以上是用XE7测试的
我的应用程序使用 TGridPanelLayout 向用户显示大量图像。当用户点击正确的图像时,所有图像都会被清除并呈现一系列新图像。将图片添加到网格的代码如下所示:
// Clear the grid of all controls, rows and columns and reinitialize
Grid.ControlCollection.Clear;
Grid.ColumnCollection.Clear;
Grid.RowCollection.Clear;
// Next follows some code to add columns and rows
// Display the names, n_images = rows * columns
for i := 0 to n_images - 1 do
begin
Image := TImage.Create (nil);
Image.HitTest := True;
if Sel_Array [i]
then Image.OnClick := test_positive
else Image.OnClick := test_negative;
c := i mod Options_Project.Cols;
r := i div Options_Project.Cols;
Image.Name := Format ('Image_%2.2d_%2.2d', [r, c]);
Image.Bitmap.LoadFromFile (Sel_Names [i]);
Image.Align := TAlignLayout.alClient;
Grid.AddObject (Image); // Grid: TGridPanelLayout
end; // for
一切正常,但问题在于重新创建 TGridPanelLayout。当第二次执行 Grid.ControlCollection.Clear
时,其中一个图像被释放时发生访问冲突。
如何在运行时清除 TGridPanellayout 而不会崩溃?还有一个问题:AddObject 是将控件添加到 TGridPanelLayout 的正确方法吗?我尝试了 AddControl 但没有显示图像。
此应用程序已在 Windows 7.
中进行测试编辑
Tom 注意到我应该分配 .Parent 并且成功了,连同 Dalija 的评论我应该使用 AddControl。以下代码有效:
for i := 0 to n_images - 1 do
begin
Image := TImage.Create (Grid);
Image.HitTest := True;
if Sel_Array [i]
then Image.OnClick := test_positive
else Image.OnClick := test_negative;
c := i mod Options_Project.Cols;
r := i div Options_Project.Cols;
Image.Name := Format ('Image_%2.2d_%2.2d', [r, c]);
Image.Bitmap.LoadFromFile (Sel_Names [i]);
Image.Align := TAlignLayout.alClient;
Image.Parent := Grid;
Grid.ControlCollection.AddControl (Image);
end; // for
谢谢大家的帮助!
调用Grid.ControlCollection.Clear删除集合中的项目是正确的。来自帮助:
Clear empties the Items array and destroys each TCollectionItem.
请注意 "destroys",这意味着它拥有管理图像生命周期的所有权和责任。
你说:
an access violation occurs when one of the images is freed.
你的意思是通过你的代码主动释放?那就是错了,AV的原因。
图片是否与用户点击并触发显示一系列新图片的图片相同?然后您需要查看代码如何在 test_positive 中操作图像,也许还有 test_negative。
要向 TGridPanelLayout 添加控件,您可以使用
Grid.AddObject(Image);
或
Image.Parent := Grid;
Grid.Controls.Add(Image);
注意,在这种情况下,您需要设置父级才能显示图像(并由网格管理)。
以上是用XE7测试的