我的应用程序使用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清空Items数组并销毁每个TCollectionItem。


请注意“销毁”,这意味着管理映像的生命周期需要所有权和责任。

你说:


当其中一幅图像被释放时,发生访问冲突。


您是要主动释放代码吗?这是错误的,也是AV的原因。

图像是否与用户单击的图像相同并触发了一系列新图像的显示?然后,您需要查看代码如何在test_positive以及也许在test_negative中操作图像。

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

Grid.AddObject(Image);


要么

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


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

上面是用XE7测试的。

关于delphi - 如何在运行时清除TGridPanelLayout,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27755379/

10-09 18:21