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 писал(а):Да, с этим кодом что-то не так. Но я, вроде бы, такого не писал в демо. Вы на что-то намекаете?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8