如何在运行时清除TGridPanelLayout

时间:2015-01-03 13:28:11

标签: delphi layout firemonkey delphi-xe5

我的应用程序使用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中进行了测试。

修改

汤姆注意到我应该已经分配了.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

谢谢大家的帮助!

1 个答案:

答案 0 :(得分:4)

调用Grid.ControlCollection.Clear来删除集合中的项是正确的。来自帮助:

  

清除清空Items数组并销毁每个TCollectionItem。

注意“破坏”,这意味着它需要管理图像生命周期的所有权和可控性。

你说:

  

在释放其中一个图像时发生访问冲突。

您的意思是主动释放您的代码吗?那是错误的和AV的原因。

图像是否与用户点击的图像相同并触发了一系列新图像的显示?然后你需要检查代码如何操作test_positive中的图像,也可能是test_negative。

要将控件添加到TGridPanelLayout,您可以使用

Grid.AddObject(Image);

Image.Parent := Grid;
Grid.Controls.Add(Image);

注意,在这种情况下,您需要设置父级以便显示图像(并由网格管理)。

以上是用XE7测试的。