Уничтожение контрола самим собой

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

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

Уничтожение контрола самим собой

Сообщение qivi » 03.09.2010 14:25:56

Проект создан как "Приложение", на форме несколько невизуальных компонентов, всё остальное создаётся и уничтожается в рунтайме. Некоторая кнопка уничтожает на форме ряд контролов включая саму себя, уничтожает следующим образом: freeandnil(B1);. При нажатии на эту кнопку программа вылетает (в линуксе после нескольких нажатий в виндовсе после первого). В консоле операционной системы пишет:
WARNING: TLCLComponent.Destroy with LCLRefCount>0. Hint: Maybe the component is processing an event?

гугл транслит:
ВНИМАНИЕ: TLCLComponent.Destroy с LCLRefCount> 0. Подсказка: Может быть, компонент обрабатывает событие?


На попытку B1.LCLRefCount:=0; - выдаёт ошибку.

Как сделать так что б она уничтожала себя и приложение не падало?
Аватара пользователя
qivi
энтузиаст
 
Сообщения: 703
Зарегистрирован: 19.01.2009 13:45:54
Откуда: Россия

Re: Уничтожение контрола самим собой

Сообщение dunin » 03.09.2010 14:55:39

qivi писал(а):...кнопка уничтожает на форме ряд контролов включая саму себя, уничтожает следующим образом: freeandnil(B1);
...

Полный код процедуры в студию плз. :wink:

Добавлено спустя 26 секунд:
Всем привет, кстати. давненько тут не был. :)
Аватара пользователя
dunin
энтузиаст
 
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и

Re: Уничтожение контрола самим собой

Сообщение VirtUX » 03.09.2010 15:23:49

я делел так:
Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormClick(Sender: TObject);
  private
    { private declarations }
    procedure OnClickB(sender: TObject);
  public
    { public declarations }
  end;

  { TBut }

  TBut = object
  private
    b: TButton;
  public
    procedure Create;
    procedure Destroy;
  end;

var
  Form1: TForm1;
  But: TBut;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormClick(Sender: TObject);
begin
  But.Create;
end;

procedure TForm1.OnClickB(sender: TObject);
begin
  But.Destroy;
end;

{ TBut }

procedure TBut.Create;
begin
  b := TButton.Create(Form1);
  b.Parent := Form1;
  //Прочие параметры
  b.OnClick:= @Form1.OnClickB;
end;

procedure TBut.Destroy;
begin
  FreeAndNil(b);
end;

end.

Можно кликать сколько душа пожелает и по форме, и по кнопке :)
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Уничтожение контрола самим собой

Сообщение Odyssey » 03.09.2010 19:14:04

Ещё, как вариант, можно вызывать уничтожение через асинхронный вызов (QueueAsyncCall):
Код: Выделить всё
procedure TForm1.DestroyButtons(Data: PtrInt);
begin
   // уничтожаем
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Application.QueueAsyncCall(@DestroyButtons, 0);
end;
В этом случае само уничтожение будет происходить уже после того, как отработает обработчик события кнопки.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Уничтожение контрола самим собой

Сообщение qivi » 03.09.2010 23:44:44

Odyssey, спасибо то что доктор прописал!
Аватара пользователя
qivi
энтузиаст
 
Сообщения: 703
Зарегистрирован: 19.01.2009 13:45:54
Откуда: Россия

Re: Уничтожение контрола самим собой

Сообщение Timid » 03.09.2010 23:47:46

Объект не может уничтожить себя через Free() внутри своего метода - это явное нарушение принципов целостности данных (в том числе ссылочных, которыми по сути являются ссылки на точки входа в функции-обработчики). Как минимум Sender станет равен nil.

Как вариант, Вы можете создать дополнительное событие, не имеющее параметров (Т.е. не имеющее параметра Sender:TObject) и подписать на него один из методов формы. В нем уже и уничтожить объект.
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15

Re: Уничтожение контрола самим собой

Сообщение zub » 04.09.2010 00:43:29

>>Объект не может уничтожить себя через Free() внутри своего метода - это явное нарушение принципов целостности данных
Почему? если гарантировано не будет попытки доступа к данным, то почему нет? Сам Free() вобщемто метод и получается уничтожение объекта внутри соего метода))

>>Как минимум Sender станет равен nil
в смысле sender для формы и self для кнопки? он не становится, а ссылается на данные которых уже небудет. Но это не беда, главное гарантировать чтобы по этой ссылке небыло попытки доступа к данным, в onClick кнопки это не гарантируется((
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Уничтожение контрола самим собой

Сообщение Timid » 04.09.2010 19:54:00

Ну да.
onClick как и любой другой обработчик вызывается ведь из какого-нибудь метода. Например, DoClick. В котором кнопка может быть перерисована, к примеру. Но она ведь уже nil !!!
Не будешь же писать каждый раз проверку на nil для себя после вызова каждого обработчика :)
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15

Re: Уничтожение контрола самим собой

Сообщение Odyssey » 04.09.2010 21:59:38

Timid писал(а):Но она ведь уже nil !!!
Не будешь же писать каждый раз проверку на nil для себя после вызова каждого обработчика :)

Проверка на nil тут не поможет. zub прав, Self после уничтожения кнопки не станет равен nil, просто будет указывать на левую память. Определить это в месте вызова нельзя, остаётся только получать runtime error.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Уничтожение контрола самим собой

Сообщение VirtUX » 04.09.2010 23:22:09

Не понимаю чем вам не нравится мой пример? Из стека в куче формируем новые объекты; из того же стека разрушаем динамики. Никаких ошибок и рядом не ляжет.
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта


Вернуться в Lazarus

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

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

Рейтинг@Mail.ru