Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Самоуничтожение визуального компонента


Автор: PosiTive 29.3.2009, 13:44
Ситуация:

динамически создаются кнопки
Код

  job_button_delete:= TButton.Create(Application);
  with job_button_delete do
  begin
    Parent:= job; // job - это фрейм
    Left:= 552;
    Top:= 39*job_count+8;
    Width:= 75;
    Height:= 25;
    Tag:= job_count;
    Caption:= 'Удалить';
    onclick:= del_job;
  end;


и обработчик onclick

Код

procedure TForm1.del_job(Sender: TObject);
begin
(Sender as TButton).Destroy;
end;


при нажатии на кнопку она удаляется, но вместе с этим выдается ошибка обращения к памяти. Как я понимаю нельзя удалять объект из собственного же метода. Может быть есть какой-нибудь ещё способ?

Заранее спасибо.

Автор: Akella 29.3.2009, 15:00
FreeAndNil?

Автор: PosiTive 29.3.2009, 15:03
Цитата(Akella @ 29.3.2009,  15:00)
FreeAndNil?

всмысле (Sender as TButton).Free?

если да, то пробовал, тоже самое :(

Автор: Akella 29.3.2009, 15:06
PosiTive, 

Цитата(PosiTive @  29.3.2009,  15:03 Найти цитируемый пост)
всмысле (Sender as TButton).Free?

нет

Добавлено через 56 секунд
Что в справке написано по FreeAndNil?

Добавлено через 4 минуты и 40 секунд
Ладно, если не можешь додумать, то вот:
Код

FreeAndNil(job_button_delete);

Автор: PosiTive 29.3.2009, 15:14
Цитата(Akella @ 29.3.2009,  15:06)
PosiTive, 

Цитата(PosiTive @  29.3.2009,  15:03 Найти цитируемый пост)
всмысле (Sender as TButton).Free?

нет

Добавлено @ 15:07
Что в справке написано по FreeAndNil?

Добавлено @ 15:10
Ладно, если не можешь додумать, то вот:
Код

FreeAndNil(job_button_delete);

таже самая ошибка памяти. 

на всякий случай кусок кода:

Код

procedure TForm1.del_job(Sender: TObject);
begin
freeandnil(Sender);
end;


Автор: Akella 29.3.2009, 15:18
Цитата(PosiTive @  29.3.2009,  15:14 Найти цитируемый пост)
на всякий случай кусок кода:


ты видишь мой кусок кода или нет?? ГДЕ ТАМ SENDER?

Автор: kami 29.3.2009, 15:19
Цитата(PosiTive @  29.3.2009,  13:44 Найти цитируемый пост)
Как я понимаю нельзя удалять объект из собственного же метода.

Правильно, нельзя.
После вызова события OnClick в процедуре TWinControl.DoKeyPress еще идет обращение к полям экземпляра класса, хотя самого экземпляра уже не существует. Отсюда AV.

Нужно реализовать "замедленное" удаление, например - через механизм сообщений Windows.

Автор: Akella 29.3.2009, 15:19
Код

 job_button_delete:= TButton.Create(сюда запихай форму, к которой принадлежит кнопка);




Цитата(PosiTive @  29.3.2009,  13:44 Найти цитируемый пост)
job_button_delete:= TButton.Create(Application);
  with job_button_delete do
  begin
    Parent:= job; // job - это фрейм
    Left:= 552;
    Top:= 39*job_count+8;
    Width:= 75;
    Height:= 25;
    Tag:= job_count;
    Caption:= 'Удалить';
    onclick:= del_job;
  end;


а где owner?

Автор: kami 29.3.2009, 15:26
Поясняю.
Мы - в обработчике события OnClick той кнопки, которую нужно уничтожить.
Само собой, что уничтожить ее напрямую нет возможности (а соблазн так велик smile ).
Тогда делаем следующий финт ушами:

Код

procedure TForm1.del_job(Sender: TObject);
begin
  PostMessage(Handle, WM_USER, integer(Sender), 0); // Именно Postmessage
end;

Объявляем приемщик сообщения:

TForm1=class(.....)
private
  procedure MyButtonDelete(var Message:TMessage); message WM_USER;
....
end;

procedure TForm1.MyButtonDelete(var Message:TMessage);
begin
  TObject(Message.Wparam).Free;
end;


Цитата(Akella @  29.3.2009,  15:19 Найти цитируемый пост)
а где owner?

Какой Owner, какой Sender?
У человека создается КУЧА кнопок динамически. Переменная job_button_delete теряет смысл сразу после выхода из процедуры создания, да и можно вполне обойтись и без нее.

Автор: PosiTive 29.3.2009, 15:37
Цитата(kami @ 29.3.2009,  15:26)
Поясняю.
Мы - в обработчике события OnClick той кнопки, которую нужно уничтожить.
Само собой, что уничтожить ее напрямую нет возможности (а соблазн так велик smile ).
Тогда делаем следующий финт ушами:

Код

procedure TForm1.del_job(Sender: TObject);
begin
  PostMessage(Handle, WM_USER, integer(Sender), 0); // Именно Postmessage
end;

Объявляем приемщик сообщения:

TForm1=class(.....)
private
  procedure MyButtonDelete(var Message:TMessage); message WM_USER;
....
end;

procedure TForm1.MyButtonDelete(var Message:TMessage);
begin
  TObject(Message.Wparam).Free;
end;


Цитата(Akella @  29.3.2009,  15:19 Найти цитируемый пост)
а где owner?

Какой Owner, какой Sender?
У человека создается КУЧА кнопок динамически. Переменная job_button_delete теряет смысл сразу после выхода из процедуры создания, да и можно вполне обойтись и без нее.

Большое спасибо за совет. У вас кошелек на Яндекс.Деньгах есть?

Автор: Akella 29.3.2009, 16:45
Цитата(kami @  29.3.2009,  15:26 Найти цитируемый пост)
Какой Owner, какой Sender?
У человека создается КУЧА кнопок динамически.

ну owner ведь должен быть у кнопки

Автор: Akella 29.3.2009, 17:45
Цитата(kami @  29.3.2009,  15:26 Найти цитируемый пост)
Мы - в обработчике события OnClick той кнопки, которую нужно уничтожить.

 smile я стормозил

Автор: THandle 29.3.2009, 19:56
Цитата(Akella @  29.3.2009,  16:45 Найти цитируемый пост)
ну owner ведь должен быть у кнопки 


Ну дык а это кто:

Цитата(Akella @  29.3.2009,  15:19 Найти цитируемый пост)
job_button_delete:= TButton.Create(Application);


Хотя можно указать и Nil, если сам убивать собираешься. Вообще kami все правильно говорит. Этот метод кстати описан в книге http://forum.vingrad.ru/books/topic-198003.html.

Автор: БелАмор 23.8.2010, 02:30
Цитата(PosiTive @  29.3.2009,  13:44 Найти цитируемый пост)
Как я понимаю нельзя удалять объект из собственного же метода

Нельзя уничтожать объект не "из собственного метода", а "из собственного обработчика". Это две большие разницы.
"Собственный метод" - это метод, объявленный в этом классе, а "собственный обработчик" - это любой (подходящий) метод любого класса (объекта которого может даже не существовать), ссылка на который хранится в свойстве OnЧтоТоТам своего объекта. Причём в большинстве случаев обработчик является не своим методом, например:
  TForm1.Button1Click - это обработсик OnClick кнопки Button1, но является методом формы Form1.

Ещё пример "большой разницы":
  Form2.Free;
Здесь Free - "свой метод", и в нём вызывается деструктор, но он не "свой обработчик"...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)