sts писал(а):непонятно, повторите вопрос
Так понимаю, что Application.QueueAsyncCall как раз и есть "отложенный запуск", про который речь идет. И он позволяет уничтожить кнопку своим же обработчиком. Верно?
Модератор: Модераторы
sts писал(а):непонятно, повторите вопрос
RRYTY писал(а):Так понимаю, что Application.QueueAsyncCall как раз и есть "отложенный запуск", про который речь идет. И он позволяет уничтожить кнопку своим же обработчиком. Верно?
procedure TApplication.ReleaseComponent(AComponent: TComponent);
var
  IsFirstItem: Boolean;
begin
  if csDestroying in AComponent.ComponentState then exit;
  //DebugLn(['TApplication.ReleaseComponent ',DbgSName(AComponent)]);
  if AppDestroying in FFlags then begin
    // free immediately
    AComponent.Free;
  end else begin
    // free later
    // => add to the FComponentsToRelease
    IsFirstItem:=FComponentsToRelease=nil;
    if IsFirstItem then
      FComponentsToRelease:=TFPList.Create
    else if FComponentsToRelease.IndexOf(AComponent)>=0 then
      exit;
    FComponentsToRelease.Add(AComponent);
    AComponent.FreeNotification(Self);
    if IsFirstItem then
      QueueAsyncCall(@FreeComponent, 0);
  end;
end;
procedure TApplication.FreeComponent(Data: PtrInt);
begin
  if Data<>0 then
    DebugLn(['HINT: TApplication.FreeComponent Data<>0 ignored']);
  ReleaseComponents;
end;
procedure TApplication.ReleaseComponents;
var
  Component: TComponent;
begin
  if FComponentsReleasing<>nil then exit; // currently releasing
  if (FComponentsToRelease<>nil) then begin
    if FComponentsToRelease.Count=0 then begin
      FreeAndNil(FComponentsToRelease);
      exit;
    end;
    // free components
    // Notes:
    //   - check TLCLComponent.LCLRefCount=0
    //   - during freeing new components can be added to the FComponentsToRelease
    //   - components can be removed from FComponentsToRelease and FComponentsReleasing
    FComponentsReleasing:=FComponentsToRelease;
    FComponentsToRelease:=nil;
    try
      while (FComponentsReleasing<>nil) and (FComponentsReleasing.Count>0) do
      begin
        Component:=TComponent(FComponentsReleasing[0]);
        FComponentsReleasing.Delete(0);
        if (Component is TLCLComponent)
        and (TLCLComponent(Component).LCLRefCount>0) then begin
          // add again to FComponentsToRelease
          ReleaseComponent(Component);
        end else begin
          // this might free some more components from FComponentsReleasing
          Component.Free;
        end;
      end;
    finally
      // add remaining to FComponentsToRelease
      while (FComponentsReleasing<>nil) and (FComponentsReleasing.Count>0) do
      begin
        Component:=TComponent(FComponentsReleasing[0]);
        FComponentsReleasing.Delete(0);
        ReleaseComponent(Component);
      end;
      FreeAndNil(FComponentsReleasing);
    end;
  end;
end;Alex2013 писал(а):Вам же нужно просто удалить кнопку из диалога а удалять из памяти необязательно ).

   RemoveComponent(TButton(Sender ));
   if (Sender is TLabel) then Application.ReleaseComponent(TLabel(Sender))
for i := 0 to labelcount - 1 do
    begin
      if Assigned(arr_svdel_text[i]) then
        s := s + 'arr_svdel_text' + IntToStr(i) + ': Y' + #13
          else s := s + 'arr_svdel_text' + IntToStr(i) + ': N' + #13;
    end;
TLabel(Sender) := nil;


Vlad04 писал(а):Не совсем понял, в чём заключается "проблема". Накидал примерный проект. Проверьте, оно?
На форме кнопка "Создать кнопку" создаёт новые кнопки и присваивает им OnClick процедуру, которая их удаляет.
Созданные в IDE кнопки Button1? Button2 и Button3 по нажатию тоже удаляются.
Всё работает без ошибок. Или я всё-таки что-то не так понял?
FreeAndNil(Sender);
Heap dump by heaptrc unit of ./Things/Lazarus/CrDelBut/project1
939 memory blocks allocated : 1558269/1559432
939 memory blocks freed     : 1558269/1559432
0 unfreed memory blocks : 0
True heap size : 1605632
True free heap : 1605632
Vlad04 писал(а):Это не ошибки. Это отчет об использовании памяти.
wwswowsogon писал(а):...
Вот демка, поясняющая проблему.
...


RRYTY писал(а):Демка:
Linux64, Lazarus 2.2.4.
Запуск 1. Удалил все, что удаляет самого себя, потом создал пять записей, после тыканья в ссылки "удалить" четвертая ссылка удалила строку, кроме себя и приложение перестало реагировать на пользователя.
Запуск 2. Создал 5 записей, на четвертом тычке во вторую ссылку сверху "удалить" осталась первая строчка и тыкаемая ссылка (вторая сверху), строка же удалилась. Дальшейшие тычки в оставшуюся ссылку приводит к полному игнорированию пользователя, как в запуске 1.
WindowsXP 32, Lazarus 2.2.4.
Создал пять записей. После четвертого тычка на второй ссылке сверху "Удалить" строка удаляется, ссылка остается. Дальнейшие тычки приводят к ошибке "Division by zero", удаляет первую строчку, дальше просто генерит ту же ошибку. Сама ссылка нагло остается. Сообщения при компиляции на скриншоте.

  for i := 0 to svcount - 1 do
    begin
      FreeAndNil(arr_svid_text[i]);
      FreeAndNil(arr_svip_text[i]);
      FreeAndNil(arr_svname_text[i]);
      FreeAndNil(arr_svopt_text[i]);
      if i = sv_index then
        begin
          //if (Sender is TLabel) then Application.ReleaseComponent(TLabel(Sender))
          RemoveComponent(TLabel(Sender));
          TLabel(Sender) := nil;
        end
          else
          FreeAndNil(arr_svdel_text[i]);
    end;
  for i := 0 to svcount - 1 do
    begin
      FreeAndNil(arr_svid_text[i]);
      FreeAndNil(arr_svip_text[i]);
      FreeAndNil(arr_svname_text[i]);
      FreeAndNil(arr_svopt_text[i]);
      FreeAndNil(arr_svdel_text[i]);
    end;
  //Убираем выбранный элемент массива серверов
  //и ссмещаем на 1 вниз значения верхних элементов, если необходимо
  if (sv_index < (svcount - 1)) then
    for i := sv_index to svcount - 2 do
      begin
        arr_svid[i] := arr_svid[i + 1];
        arr_svname[i] := arr_svname[i + 1];
        arr_svip[i] := arr_svip[i + 1];
      end;
var
  i, k: word;
begin
  k := 0;
  for i := 0 to k - 1 do
  begin
  end;
    arr_svid, arr_svname, arr_svip: Array of String;
    arr_svid_text, arr_svname_text,
    arr_svip_text, arr_svopt_text, arr_svdel_text: Array of TLabel;
type
  TMyServer = record
    arr_svid, arr_svname, arr_svip: String;
    arr_svid_text, arr_svname_text,
    arr_svip_text, arr_svopt_text, arr_svdel_text: TLabel;
  end;
var
  arr_server: array of TMyServer;

Vlad04 писал(а):wwswowsogon
Посмотрел Вашу демку внимательно...
Во-первых, почему Вы удаляете 4 массива полностью, а пятый - нет?
- Код: Выделить всё
for i := 0 to svcount - 1 do
begin
FreeAndNil(arr_svid_text[i]);
FreeAndNil(arr_svip_text[i]);
FreeAndNil(arr_svname_text[i]);
FreeAndNil(arr_svopt_text[i]);
if i = sv_index then
begin
//if (Sender is TLabel) then Application.ReleaseComponent(TLabel(Sender))
RemoveComponent(TLabel(Sender));
TLabel(Sender) := nil;
end
else
FreeAndNil(arr_svdel_text[i]);
end;
Vlad04 писал(а):Правильно, в данном случае будет так
- Код: Выделить всё
for i := 0 to svcount - 1 do
begin
FreeAndNil(arr_svid_text[i]);
FreeAndNil(arr_svip_text[i]);
FreeAndNil(arr_svname_text[i]);
FreeAndNil(arr_svopt_text[i]);
FreeAndNil(arr_svdel_text[i]);
end;
procedure TMain.DelSVAll();
var
  sv_index: Word;
begin
  for sv_index := 0 to svcount - 1 do
    begin
      FreeAndNil(arr_svid_text[sv_index]);
      FreeAndNil(arr_svip_text[sv_index]);
      FreeAndNil(arr_svname_text[sv_index]);
      FreeAndNil(arr_svopt_text[sv_index]);
      FreeAndNil(arr_svdel_text[sv_index]);
    end; 
Vlad04 писал(а):Хотя, имхо, весьма сомнительно каждый раз удалять и создавать массив полностью. Лучше удалять только указанный элемент, остальные сдвигать. Вы же 3 массива сдвигаете
- Код: Выделить всё
//Убираем выбранный элемент массива серверов
//и ссмещаем на 1 вниз значения верхних элементов, если необходимо
if (sv_index < (svcount - 1)) then
for i := sv_index to svcount - 2 do
begin
arr_svid[i] := arr_svid[i + 1];
arr_svname[i] := arr_svname[i + 1];
arr_svip[i] := arr_svip[i + 1];
end;
Vlad04 писал(а):Но самая главная проблема имеет элементарное решение: замените все word на integer и всё взлетит.
 Программа по-прежнему ведёт себя странно, ну и память от объекта не освобождается.
 Программа по-прежнему ведёт себя странно, ну и память от объекта не освобождается. Vlad04 писал(а):До какого значения, по Вашему мнению будет продолжаться следующий цикл? Чему в цикле будут равны i и k?
- Код: Выделить всё
var
i, k: word;
begin
k := 0;
for i := 0 to k - 1 do
begin
end;
 Но я, вроде бы, такого не писал в демо. Вы на что-то намекаете?
 Но я, вроде бы, такого не писал в демо. Вы на что-то намекаете? 
Vlad04 писал(а):И ещё. Если вам нужно описать набор объектов, то лучше использовать не несколько массивов, а массив записей.
Вместо
- Код: Выделить всё
arr_svid, arr_svname, arr_svip: Array of String;
arr_svid_text, arr_svname_text,
arr_svip_text, arr_svopt_text, arr_svdel_text: Array of TLabel;
записать
- Код: Выделить всё
type
TMyServer = record
arr_svid, arr_svname, arr_svip: String;
arr_svid_text, arr_svname_text,
arr_svip_text, arr_svopt_text, arr_svdel_text: TLabel;
end;
var
arr_server: array of TMyServer;
wwswowsogon писал(а):Да, с этим кодом что-то не так.Но я, вроде бы, такого не писал в демо. Вы на что-то намекаете?

Сейчас этот форум просматривают: Yandex [Bot] и гости: 1