1

我在运行时创建了一个 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 这样的可视化组件?

4

1 回答 1

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它会检查。

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

于 2020-07-30T10:17:24.750 回答