【问题标题】:How to Create and Destroy TGrid at Runtime in Firemonkey — Android and iOS App Dev如何在 Firemonkey 运行时创建和销毁 TGrid — Android 和 iOS App Dev
【发布时间】:2020-11-20 01:21:03
【问题描述】:

我在运行时创建了一个 TGrid。该过程要求我在单击“添加项目并刷新”按钮重新创建之前销毁 TGrid。我注意到,如果我在重新创建 TGrid 之前不销毁它,那么沉重的开销会导致我的应用在执行 8 次或更多次时冻结。

我尝试了以下代码但无济于事:

procedure TformMain.AddItemRefreshClick(Sender: TObject);
var
  TGrid1 : TTGrid;
begin
  if Assigned(TGrid1) then
  begin
    TGrid1.DisposeOf;
    {TGrid1.Free;    Tried this also but not working}
    {TGrid1 := nil;  Tried this also but not working}
  end;

  TGrid1 := TTGrid.Create(formMain);
  With TGrid1 do
  begin
    Parent := formMain;
    Align := TAlignLayout.Client;
    Margins.Top := 5;
    Margins.Left := 5;
    Margins.Right := 5;
    Margins.Bottom := 5;
    ScrollBars.Visible := True;
    Header.Format.Font.Size := 11;
    Cells.Format.Font.Size := 11;
    TabOrder := 0;
  end;
end;

我在地址处遇到访问冲突...听起来很糟糕!

有没有更简单的方法可以在运行时创建和销毁像 TGrid 这样的可视化组件?

【问题讨论】:

  • 感谢提醒(已更新)。我做了你的建议,见下文,但我得到了相同的访问冲突.. if Assigned(CanvassGrid) 然后开始 FreeAndNil(CanvassGrid);结束;
  • 您必须使用全局变量来存储网格,以便在调用此方法之间保留其地址。那就是问题所在。 (目前TGrid1(对象实例变量的名字很奇怪,因为它以T开头!)是一个非托管类型的局部变量,所以在方法的开头它是未初始化的。因此,它是一个随机指针!)然后你应该做MyGrid.Free,或者——甚至更好——FreeAndNil(MyGrid)。不需要if Assigned(...),因为Free 会自行检查。
  • 完美!我使用了全局变量,如果分配则删除,现在它可以工作了!请发布您的答案并将其标记为已回答。非常感谢。

标签: delphi firemonkey tcomponent


【解决方案1】:

您必须使用非局部变量来存储网格,以便在调用此方法之间保留其地址。

目前,TGrid1 是一个局部变量。这实质上意味着它是每次调用例程时创建的变量。它的值不会在调用之间保存。而且在Delphi中,非托管类型的局部变量没有初始化,所以这基本上是一个随机指针。使用它是非常危险的! (而Assigned 不会帮助你,因为随机指针很可能是非零的,因为它是......好吧,随机的。)

(顺便说一句,变量名称TGrid1 非常混乱,因为它以T 开头。通常只有类型名称以T 开头。)

所以改为在你的表单类中添加一个私有字段:

  private
    FMyGrid: TGrid;

(不知道类名是:在你的Q里,TTeeGridTTGrid都写了。)

那你就可以了

procedure TformMain.AddItemRefreshClick(Sender: TObject);
begin

  // Free old grid
  FreeAndNil(FMyGrid);

  // Create new grid
  FMyGrid := TGrid.Create(formMain);
  with FMyGrid do
  begin
    Parent := formMain;
    Align := TAlignLayout.Client;
    Margins.Top := 5;
    Margins.Left := 5;
    Margins.Right := 5;
    Margins.Bottom := 5;
    ScrollBars.Visible := True;
    Header.Format.Font.Size := 11;
    Cells.Format.Font.Size := 11;
    TabOrder := 0;
  end;

end;

FreeAndNil(FMyGrid) 基本上执行FMyGrid.Free 并将指针设置为nil,这样您就不会在TGrid.Create 构造函数引发异常的情况下最终得到一个悬空指针。

此外,不需要if Assigned(FMyGrid) then 部分,因为FMyGrid.Free 会进行检查。

还要注意FMyGrid 现在是一个类的成员,因此它从一开始就被初始化为nil

【讨论】:

  • 抱歉混淆,但已经更新了我的问题。实际上,我使用的是 TeeGrid,但我在这里简化了 TGrid,但它是一样的。不到15分钟,这个案子就解决了。非常感谢!
  • @RickyBelmont:没问题!很高兴我能帮上忙。
  • 最后一件事。我刚刚尝试在 iOSSimulator 中运行它,但在点击 8 次后,它会冻结一段时间,比如 2-3 分钟或更长时间,点击次数更多,同样的问题。此解决方案是否直接适用于 iOS 和 Android?
  • @RickyBelmont:我不了解 iOS 和 Android,但很可能该问题与本问答中讨论的代码无关。因此,如果不查看您的其他代码,我们将无法帮助您。
  • 你说得对,我可能需要再次检查我的查询。似乎我需要限制在运行时创建的列数,因为每次单击按钮都会创建不确定的列数。我必须将其限制为 10 列。这可能会解决我的问题。还是谢谢。
猜你喜欢
  • 2015-03-16
  • 1970-01-01
  • 2020-09-12
  • 2013-10-01
  • 2016-05-20
  • 1970-01-01
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多