Как создать и уничтожить TGrid во время выполнения в Firemonkey - разработчик приложений для Android и iOS

У меня есть 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, во время выполнения?

1 ответ

Решение

Вы должны использовать нелокальную переменную для хранения сетки, чтобы ее адрес сохранялся между вызовами этого метода.

В данный момент, TGrid1это локальная переменная. По сути, это означает, что это переменная, которая создается каждый раз при вызове подпрограммы. Его значение не сохраняется между вызовами. А в Delphi локальные переменные неуправляемых типов не инициализируются, так что это в основном случайный указатель. Работать с ним очень опасно! (А такжеAssigned не поможет вам, поскольку случайный указатель вполне может быть ненулевым, потому что он... ну, случайный.)

(Кстати, имя переменной TGrid1 очень сбивает с толку, поскольку начинается с T. Обычно только имена типов начинаются сT.)

Поэтому вместо этого добавьте частное поле в свой класс формы:

  private
    FMyGrid: TGrid;

(Я не знаю, что имя класса: в вашем Q вы пишете оба TTeeGrid а также TTGrid.)

Тогда ты можешь сделать

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 now является членом класса и поэтому инициализируется как nil с самого начала.

Другие вопросы по тегам