Удаление компонента по щелчку (самого себя)

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Удаление компонента по щелчку (самого себя)

Сообщение wwswowsogon » 16.11.2023 22:04:35

Всем доброго времени суток!

Неожиданно столкнулся с проблемой: необходимо удалить по щелчку по Button / BitBtn / Label саму эту сущность.

На старых форумах по Delphi предлагается использовать стандартный подход:

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
begin
  (Sender as TButton).Free;
end;


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

Я понял, что есть два рабочих способа: либо через таймер, либо через WinAPI. Можно, конечно, попробовать ещё по щелчку скрывать компонент, а потом при каких-то событиях формы его удалять, опять же. Но, возможно, есть что-то более изящное?

Через WinAPI не хочется, по причине прицела на кроссплатформенность. Возможно, есть некий аналогичный способ для Linux.
wwswowsogon
постоялец
 
Сообщения: 152
Зарегистрирован: 23.12.2008 20:41:37

Re: Удаление компонента по щелчку (самого себя)

Сообщение DedFrend » 16.11.2023 22:17:25

Одно из стандартных решений - послать сообщение форме, чтобы она удалила компонент, а в форме организовать обработку этого сообщения. Правда, понятия не имею, как это работает в Линукс
DedFrend
постоялец
 
Сообщения: 156
Зарегистрирован: 25.11.2018 12:21:50

Re: Удаление компонента по щелчку (самого себя)

Сообщение RRYTY » 16.11.2023 22:31:52

У меня корректно работает. Без всяких таймеров. Одна тонкость - удаляю компоненты, которые программно создаю.
RRYTY
постоялец
 
Сообщения: 208
Зарегистрирован: 25.12.2021 10:00:32

Re: Удаление компонента по щелчку (самого себя)

Сообщение iskander » 16.11.2023 22:48:15

Application.ReleaseComponent()?
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
begin
  if Sender is TComponent then
    Application.ReleaseComponent(TComponent(Sender));
end;
iskander
энтузиаст
 
Сообщения: 606
Зарегистрирован: 08.01.2012 18:43:34

Re: Удаление компонента по щелчку (самого себя)

Сообщение wwswowsogon » 17.11.2023 11:36:39

RRYTY писал(а):У меня корректно работает. Без всяких таймеров. Одна тонкость - удаляю компоненты, которые программно создаю.


Через Free?

Код: Выделить всё
Component.Free


Добавлено спустя 6 минут 42 секунды:
iskander писал(а):Application.ReleaseComponent()?
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
begin
  if Sender is TComponent then
    Application.ReleaseComponent(TComponent(Sender));
end;


Да, точно, работает. Спасибо огромное.

На форумах видел, что вроде как в новых версиях Delphi есть метод Release у самого компонента. В методах Application не догадался посмотреть. :)
wwswowsogon
постоялец
 
Сообщения: 152
Зарегистрирован: 23.12.2008 20:41:37

Re: Удаление компонента по щелчку (самого себя)

Сообщение Alex2013 » 17.11.2023 18:56:14

Я делал примерно так .(ИМХО) так надежнее.
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
begin
if Sender is TComponent then
Begin
   RemoveComponent(TButton(Sender ));
   TButton(Sender).Free;
end
end;
Alex2013
долгожитель
 
Сообщения: 3049
Зарегистрирован: 03.04.2013 11:59:44

Re: Удаление компонента по щелчку (самого себя)

Сообщение wwswowsogon » 18.11.2023 12:58:19

Alex2013 писал(а):Я делал примерно так .(ИМХО) так надежнее.
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
begin
if Sender is TComponent then
Begin
   RemoveComponent(TButton(Sender ));
   TButton(Sender).Free;
end
end;

Хм, однако, этот способ даёт Access Violation на строке

Код: Выделить всё
(TBitBtn(Sender)).Free;
wwswowsogon
постоялец
 
Сообщения: 152
Зарегистрирован: 23.12.2008 20:41:37

Re: Удаление компонента по щелчку (самого себя)

Сообщение Alex2013 » 19.11.2023 15:29:45

wwswowsogon писал(а):
Alex2013 писал(а):Я делал примерно так .(ИМХО) так надежнее.
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
begin
if Sender is TComponent then
Begin
   RemoveComponent(TButton(Sender ));
   TButton(Sender).Free;
end
end;

Хм, однако, этот способ даёт Access Violation на строке

Код: Выделить всё
(TBitBtn(Sender)).Free;

Free тут по большему счету не нужен (но если очень хочется можно сделать "крюк" через таймер или поток(тут можно даже по идее обойтись одной строчкой кода ) но "нафига козе боян"? Вам же нужно просто удалить кнопку из диалога а удалять из памяти необязательно ) . Еще вариант сделать проверку в Iidle
if (Button1<>Nil) and (form1.Components.IndexOf( Button1) =-1) then begin Button1.free; Button1:=Nil end;
Почему я против Application.ReleaseComponent ? Потому что точно непонятно что делает это метод и какие у него ограничения. :idea:
Alex2013
долгожитель
 
Сообщения: 3049
Зарегистрирован: 03.04.2013 11:59:44

Re: Удаление компонента по щелчку (самого себя)

Сообщение DedFrend » 19.11.2023 22:45:55

Что-то мне показалось, что в обсуждении не понимают проблемы. Решил встрять. Дело в том, что в объекте TButton будет код типа такого
Код: Выделить всё
if assigned(OnClick) then
  OnClick(Sender);

но если в этом вызове OnClick уничтожается сам объект, который его вызывал, то возникает неопределенность с дальнейшим выполнением.
Куда попадет управление после выхода из onClick? К каким свойствам можно будет обратиться? (Ведь self уже недействителен). Поэтому
разрушать объект прямо в обработчике просто нельзя. Оно может сработать, а может и нет.
Кстати, вместо удаления его можно сделать невидимым Sender.Visible := false. Это абсолютно безопасно.
DedFrend
постоялец
 
Сообщения: 156
Зарегистрирован: 25.11.2018 12:21:50

Re: Удаление компонента по щелчку (самого себя)

Сообщение Alex2013 » 20.11.2023 13:02:33

1 Свешено верно ! Если "убивать" одну кнопку другой кнопкой то все будет тип-топ .

2 Так я как раз и пишу что нужно сделать RemoveComponent а Free или не делать или сделать "отложенный запуск" через таймер или поток или проверить факт удаления в обработчике onidle.
(То есть за пределами обработчика нажатия )

3 Sender.Hide во многих случаях не поможет (особенно если нужно гарантировано прервать обработку событий именно в текущий момент ) и даже Sender.enable:=false; Sender.Hide; не обязательно сработает мгновенно . А вот после RemoveComponent можно быть полностью уверенным, что обработка всего потока событий "от окна" остановлена и завершена ( у меня так медиаплеер динамически удаляется с формы ).
Alex2013
долгожитель
 
Сообщения: 3049
Зарегистрирован: 03.04.2013 11:59:44

Re: Удаление компонента по щелчку (самого себя)

Сообщение RRYTY » 20.11.2023 15:10:26

https://wiki.lazarus.freepascal.org/Asy ... s_Calls/ru

Прокомментируйте, плз.
Код: Выделить всё
Обратите внимание, что это более обобщенная версия ReleaseComponent, и ReleaseComponent вызывает этот метод.
Врут, что ли? Хочется понять, что происходит.
RRYTY
постоялец
 
Сообщения: 208
Зарегистрирован: 25.12.2021 10:00:32

Re: Удаление компонента по щелчку (самого себя)

Сообщение sts » 20.11.2023 16:02:29

RRYTY писал(а):Врут, что ли? Хочется понять, что происходит.

непонятно, повторите вопрос

в написанном нет противоречия
sts
постоялец
 
Сообщения: 431
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Re: Удаление компонента по щелчку (самого себя)

Сообщение iskander » 20.11.2023 16:43:07

Alex2013 писал(а):1 Свешено верно ! Если "убивать" одну кнопку другой кнопкой то все будет тип-топ .

2 Так я как раз и пишу что нужно сделать RemoveComponent а Free или не делать или сделать "отложенный запуск" через таймер или поток или проверить факт удаления в обработчике onidle.
(То есть за пределами обработчика нажатия )

3 Sender.Hide во многих случаях не поможет (особенно если нужно гарантировано прервать обработку событий именно в текущий момент ) и даже Sender.enable:=false; Sender.Hide; не обязательно сработает мгновенно . А вот после RemoveComponent можно быть полностью уверенным, что обработка всего потока событий "от окна" остановлена и завершена ( у меня так медиаплеер динамически удаляется с формы ).

Alex2013 не читатель, Alex2013 писатель?
iskander
энтузиаст
 
Сообщения: 606
Зарегистрирован: 08.01.2012 18:43:34

Re: Удаление компонента по щелчку (самого себя)

Сообщение wwswowsogon » 20.11.2023 21:01:32

Alex2013 писал(а):Free тут по большему счету не нужен


Я только за. :) Чем проще, тем лучше.

Alex2013 писал(а):3 Sender.Hide во многих случаях не поможет


Да, в моём случае это может создать дополнительные сложности, потому что заранее неизвестно, сколько будет таких компонентов, и когда и как они будут удаляться и создаваться. Можно запутаться.
wwswowsogon
постоялец
 
Сообщения: 152
Зарегистрирован: 23.12.2008 20:41:37

Re: Удаление компонента по щелчку (самого себя)

Сообщение Alex2013 » 21.11.2023 02:33:49

iskander писал(а):
Alex2013 писал(а):1 Свешено верно ! Если "убивать" одну кнопку другой кнопкой то все будет тип-топ .

2 Так я как раз и пишу что нужно сделать RemoveComponent а Free или не делать или сделать "отложенный запуск" через таймер или поток или проверить факт удаления в обработчике onidle.
(То есть за пределами обработчика нажатия )

3 Sender.Hide во многих случаях не поможет (особенно если нужно гарантировано прервать обработку событий именно в текущий момент ) и даже Sender.enable:=false; Sender.Hide; не обязательно сработает мгновенно . А вот после RemoveComponent можно быть полностью уверенным, что обработка всего потока событий "от окна" остановлена и завершена ( у меня так медиаплеер динамически удаляется с формы ).

Alex2013 не читатель, Alex2013 писатель?

Чукча, просто Чукча .... :mrgreen: (самоирония)

Добавлено спустя 17 минут 16 секунд:
wwswowsogon писал(а):Да, в моём случае это может создать дополнительные сложности, потому что заранее неизвестно, сколько будет таких компонентов, и когда и как они будут удаляться и создаваться. Можно запутаться.

Иногда нужно сразу после снятия-отключения некого "активного компонента" менять содержимое формы (переключать видимость панелей или менять их размеры и т.п.) так вот если ДО ЭТОГО не убрать его из списка "активных компонент " может произойти сбой в прорисовке окна ( причем временами довольно дикий типа "зомби-фейма" весящего до выхода из системы или полной перезагрузки (кстати этим временами грешат некоторые видеоплееры - возможно по сходным причинам ) )
Alex2013
долгожитель
 
Сообщения: 3049
Зарегистрирован: 03.04.2013 11:59:44

След.

Вернуться в Lazarus

Кто сейчас на конференции

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

Рейтинг@Mail.ru