【问题标题】:How to clear a TGridPanelLayout at runtime如何在运行时清除 TGridPanelLayout
【发布时间】:2015-01-03 13:28:11
【问题描述】:

我的应用程序使用 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

感谢大家的帮助!

【问题讨论】:

  • 现在我还没有用 TGridPanelLayour 醒来,所以我无法为您提供直接答案,但我想知道一些事情。你总是呈现相同数量的图像吗?如果你是,那你为什么每次都摧毁它们?简单地更改它显示的图像(加载新的位图)并更改将为 OnClick 事件触发的方法不是更容易和更有效吗?
  • 你是完全正确的,这是我的问题:下一个演示文稿的行和列可能会改变。
  • TImage.Create(Grid) 怎么样,然后使用Grid.AddControl(Image) 我只是猜测,因为我没有 XE5 并且 TGridPanelLayout 在 XE4 中不可用。
  • 这是有道理的,我只是这样做了(请参阅问题的结尾)但是当我这样做时,没有显示任何图像。

标签: delphi layout firemonkey delphi-xe5


【解决方案1】:

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

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

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

你说:

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

您的意思是通过您的代码主动释放吗?那么这是错误的,也是AV的原因。

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

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

Grid.AddObject(Image);

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

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

以上是用XE7测试的。

【讨论】:

  • 分配 .Parent 成功了。我稍微修改了代码并使用AddControl 而不是.Add 或.AddObject。请参阅已编辑的问题。为避免误解:我自己不会破坏图像,这只是Grid.ControlCollection.Clear 的(正确)结果。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2020-08-18
  • 2017-08-31
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
  • 1970-01-01
  • 2020-07-09
相关资源
最近更新 更多