I have a TGrid created at runtime. The procedure requires that I should destroy TGrid before I can re-create at "add item and refresh" button click. I noticed that if I don't destroy TGrid before re-creating it, heavy overheads cause to freeze my App on over 8 or more times of doing it.
I tried the following codes but no avail:
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;
I am getting Access Violation at Address... Sounds heave error!
Is there a simpler way that I can create and destroy visual component like TGrid at runtime?
You must use a non-local variable to store the grid, so that its address is preserved between invocations of this method.
Currently, TGrid1
is a local variable. That essentially means that it is a variable that is created each time the routine is called. Its value isn't saved between invocations. And in Delphi, local variables of unmanaged types are not initialised, so that this is basically a random pointer. It is very dangerous to work with it! (And Assigned
won't help you, since a random pointer might well be non-zero because it is ... well, random.)
(As an aside, the variable name TGrid1
is very confusing, since it starts with T
. Usually only type names start with T
.)
So instead add a private field to your form class:
private
FMyGrid: TGrid;
(I don't know that the class name is: in your Q, you write both TTeeGrid
and TTGrid
.)
Then you can do
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)
basically does FMyGrid.Free
and also sets the pointer to nil
so that you won't end up with a dangling pointer in case the TGrid.Create
constructor should raise an exception.
Furthermore, there is no need for the if Assigned(FMyGrid) then
part, because FMyGrid.Free
does that check.
Also notice that FMyGrid
now is a member of a class, and as such it is initialised to nil
from the beginning.