Перейти к содержанию
Fire Monkey от А до Я

Как убить кнопку кликнув на нее саму


gonzales

Рекомендуемые сообщения

59 минут назад, kami сказал:

помнится, отвечал уже кому-то на форуме. Для динамически создаваемых компонентов просто не указывайте имя. Не нужно оно им. Тогда эта проблема отпадает сама собой.

я про TFrame..  конечно всяким TLable и т.п. имя назначать ни к чему... Фреймы получают имя в designtime и создаются (динамически) с этим именем.

Ссылка на комментарий
6 минут назад, slav_z сказал:

я про TFrame..  конечно всяким TLable и т.п. имя назначать ни к чему... Фреймы получают имя в designtime и создаются (динамически) с этим именем.

сделай "генератор имен" компонентов!  и при создании назначай!

Ссылка на комментарий
4 минуты назад, #WAMACO сказал:

сделай "генератор имен" компонентов!  и при создании назначай!

да нет смысла... это сложнее чем назначить пустое имя при создании.

F:=TFrameClass.Create(Self);
F.Name:='';
...

 

Ссылка на комментарий
2 часа назад, kami сказал:

помнится, отвечал уже кому-то на форуме. Для динамически создаваемых компонентов просто не указывайте имя. Не нужно оно им. Тогда эта проблема отпадает сама собой.

А разве если создавать по типу 

for i:=0 to 5 do begin

  a := tframe.create(self);

end;

не будет ошибки дублирования? по моему будет. по этой причине именовали := 'frame_'+i.toString;

Ссылка на комментарий
function CreateGUID(): string;
var
    GUID: TGUID;
begin
    if ( System.SysUtils.CreateGUID(GUID) <> 0 ) then
        Result := ''
    else
        Result := GUIDToString(GUID);
end;

...

begin
    ...
    lFrame.Name := CreateGUID();
end;

Это чтобы уж совсем быть уверенным)))

PS. В Delphi 7 - 100% можно создавать компоненты не присваивая ему имя, у нас так все справочники в CRM работали.

Ссылка на комментарий
4 часа назад, FREEFAR сказал:

не будет ошибки дублирования? по моему будет. по этой причине именовали := 'frame_'+i.toString;

попробовать религия не позволяет?

Только что написанный код:

var
  i: Integer;
  fr: TFrame13; // отдельный фрейм, у которого в ObjectInspector так и написано: Name = Frame13
begin
  for i := 0 to 5 do
    begin
      fr:=TFrame13.Create(nil);
      fr.Parent:=Self;
      fr.Align:=alRight;
    end;

всё отрабатывает без проблем, никаких вопросов по именованию рантайм-компонентов не возникает.

Ссылка на комментарий
2 часа назад, slav_z сказал:

проверка на дублирование имени выполняется родителем... а он у тебя nil

Родитель-то как раз не nil. Владелец nil.

Позвольте поинтересоваться, а какой профит помимо счастья обладания геморроем (который сам себе же и сделал) принесет создание компонента с указанием владельца?
Единственный плюс, который мог бы быть - владелец при высвобождении себя уничтожает всё, чем он владеет.

Но вот беда-то... родитель тоже это делает, причем - раньше. И благодаря подпискам на уведомления владелец узнаёт, что компонента, которым он владел, уже нет, т.е. попытки двойного уничтожения НЕ будет.

Ссылка на комментарий

Вы выискиваете какие-то обходные маневры, генерацию уникальных имен с привлечением guid, обнуление имени после создания...

а на самом деле ничего из этих костылей не нужно.

Ссылка на комментарий

разработчики FMX по каким-то неведомым причинам сделали так, что визуальный контейнер при своем уничтожении так же разрушает и те компоненты, которые отображает (достаточно было просто обнулить Parent). такого никогда не было в VCL. это плохо и неправильно. это работа Owner а не Parent.

Поробуйте создать элемент Create(Owner) и указать какой-нибудь посторонний Parent не принадлежащий Owner. При разрушении получите AV (сначала элемент будет разрушен Parent-ом а затем то же самое попытается сделать и Owner...  нет там никаких нотификаций и подписок).

я постараюсь далее не вступить в спор...  но ничего не обещаю...

Ссылка на комментарий
5 часов назад, kami сказал:

попробовать религия не позволяет?

Только что написанный код:


var
  i: Integer;
  fr: TFrame13; // отдельный фрейм, у которого в ObjectInspector так и написано: Name = Frame13
begin
  for i := 0 to 5 do
    begin
      fr:=TFrame13.Create(nil);
      fr.Parent:=Self;
      fr.Align:=alRight;
    end;

всё отрабатывает без проблем, никаких вопросов по именованию рантайм-компонентов не возникает.

Откуда узнал про религию дядя?

Ссылка на комментарий
56 минут назад, slav_z сказал:

это работа Owner а не Parent.

Уничтожение и в VCL и в FMX идет именно Parent-ом. Owner получал уведомления (FreeNotification / RemoveFreeNotifications) и убирал высвобожденные ссылки из своего списка на уничтожение. Потом уничтожал свое.
Это дефолтное поведение, сложившееся издавна, оно же без изменений перекочевало в FMX, единственное - находятся методы FreeNotification / RemoveFreeNotifications в разных классах.

1 час назад, slav_z сказал:

При разрушении получите AV (сначала элемент будет разрушен Parent-ом а затем то же самое попытается сделать и Owner...  нет там никаких нотификаций и подписок). 

Нет, это далеко не так. Parent-ом действительно уничтожается всё дочернее. Но Owner после этого ничего сделать уже не может, потому что он уже не знает об уничтоженном компоненте:

destructor TComponent.Destroy;
begin
...
  if FOwner <> nil then FOwner.RemoveComponent(Self);

Ну и напоследок:

procedure TForm12.btn1Click(Sender: TObject);
var
  fm: TForm;
  fr: TFrame13;
  i: Integer;
begin
  fm := TForm12.Create(Self); // создаем дубликат
  try
    for i := 0 to 5 do
      begin
        fr := TFrame13.Create(Self); // Owner - главная форма
        // на фрейм накидал эдитов, лейблов - чтобы не пусто было.
        fr.Name := 'fr' + IntToStr(i);
        fr.Parent := fm; // а Parent - вторая форма того же класса.
        fr.Align := TAlignLayout.Right;
      end;
    fm.ShowModal;
  finally
    fm.Free; // уничтожаем вторую форму
  end;
  // и потом, при закрытии главной формы всё кошерно.
end;

Что я делаю не так?

Ссылка на комментарий
6 минут назад, FREEFAR сказал:

Откуда узнал про религию дядя?

Предположил на основании твоего вывода " не будет ошибки дублирования? по моему будет ", который проверяется и опровергается за 2 минуты.
В результате вместо того, чтобы понять откуда ноги растут у ошибки дублирования имен - вы имеете костыли типа "по этой причине именовали := 'frame_'+i.toString; "

Ссылка на комментарий

Upd. Нет, похоже в fmx механизм FreeNotification не используется для уничтожения. Но это не мешает всему хозяйству уничтожаться корректно, какие бы родители с владельцами ни указывались

Ссылка на комментарий
6 минут назад, kami сказал:

Предположил на основании твоего вывода " не будет ошибки дублирования? по моему будет ", который проверяется и опровергается за 2 минуты.
В результате вместо того, чтобы понять откуда ноги растут у ошибки дублирования имен - вы имеете костыли типа "по этой причине именовали := 'frame_'+i.toString; "

Предполагай по сути вопроса. А не отвлекаясь на офТоп. Или там в Питере культуре особо не учат? Или тебя ранило походу где-то, чем-то, как-то.
Всем успел накидать я смотрю

Ссылка на комментарий

Зря Вы TPurgatory угробили :)
 

Простой пример:

при потере фокуса закрывается всплывающее меню и разрушается всплывающая форма с этим меню,

на OnClick всплывающего меню повешен обработчик,

в обработчике возникает исключение которое приводит к появлению окошка с сообщением об ошибке

появление окна с сообщением об ошибке закрывает и разрушает контекстное меню

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

Подобные ситуации могут возникнуть и в других, менее очевидных случаях. Так что будьте бдительны.

Ссылка на комментарий

Да тут баг на баге сидит и погоняет

Вот еще в духе этой темы: грид, лайвбиндинг.В Grid1HeaderClick выполняем обновление запроса (например, для сортировки). После этого форма перестает реагировать на мышь))

Уже впадлу багрепорты писать, штук 15 настрочил наверное а то и больше

Решил пока через таймер...

Ссылка на комментарий
7 часов назад, FREEFAR сказал:

Предполагай по сути вопроса. А не отвлекаясь на офТоп. Или там в Питере культуре особо не учат? Или тебя ранило походу где-то, чем-то, как-то.
Всем успел накидать я смотрю

Понаехавших - нет, не учат. Раненых особенно. Тебе эпитеты тоже подобрать? По сути вопроса?

Как ты говоришь "накидывание" возникло от того, что для решения не самого сложного вопроса здесь озвучены (в том числе -тобой)  рекомендации и выводы, от которых потом сложно не удивляться - откуда столько говнокода в экосистеме Делфи?
Да вот отсюда, из таких топиков на форумах, которые неокрепшие (да и окрепшие) умы впитывают и несут потом в массы. Удивительно, что еще не затронули "уникальное имя нужно, потому что по нему потом будем искать этот компонент"...

Ссылка на комментарий
  • Администраторы
13 часов назад, slav_z сказал:

Поробуйте создать элемент Create(Owner) и указать какой-нибудь посторонний Parent не принадлежащий Owner. При разрушении получите AV (сначала элемент будет разрушен Parent-ом а затем то же самое попытается сделать и Owner...  нет там никаких нотификаций и подписок).

А есть вообще понимание:

  1. Что такое Овнер для компонентов в делфи?
  2. Какую роль он играет в дизайнере и в рантайме?
Ссылка на комментарий
13 часов назад, kami сказал:

Вы выискиваете какие-то обходные маневры, генерацию уникальных имен с привлечением guid, обнуление имени после создания...

а на самом деле ничего из этих костылей не нужно.

Мой шеф любил говорить:
-Мы сами создаем себе проблемы, а потом героически их преодолеваем.

Штука с GUID была шуткой, я видимо должен был был это указать)))))

Ссылка на комментарий

Не ссоритесь девочки пож. :)

В 18.01.2017 в 17:57, gonzales сказал:

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

Помогите советом, как убить кнопку кликнув на нее...

Возвращаясь к сути вопроса. Основная сложность тут в том, что в Delphi нельзя разрушать экземпляр класса внутри метода этого класса за исключением тех случаев, когда метод использует только для разрушения Free, DisposeOf. Почему так, а не иначе, какие есть исключения и почему "уменяфсёработает" объяснять долго, поэтому в первом приближении предлагаю принять это за аксиому.
Обработчики событий OnClick и пр. вызываются из методов классов, так что разрушать контрол внутри события нельзя от слова совсем. Кроме очевидных случаев типа Self.DisposeOf существуют более запутанные варианты, когда к примеру закрывает и разрушается форма, что приводит к разрушению всех дочерних контролов.

Образно говоря, самоубийства строго запрещены, но не запрещено нанимать киллера и в качестве жертвы указывать себя. Т.е. должен быть некий другой (глобальный) объект который будет разрушать объекты, которые хотели бы самоубицо. Реализацию такого объекта можете придумать сами, или использовать TPurgatory (чистилище, в католическом учении — промежуточное место между раем и адом). Но чтобы убедиться в правильности работы можно создать своего наследника TButton в котором перекрыть деструктор и поставить в нем точку останова. При запуске в режиме отладки посмотрите стек вызова деструктора (надо быть внимательным, он может быть длиннющим), ни где в этом стеке не должно быть метода разрушаемого экземпляра. Если в Вы нашли метод разрушаемого объекта (за исключением вышеуказанных), то Ваш способ удаления работает не правильно и с некоторой долей вероятности будет приводить к AV и другим "неприятностям" которые почти невозможно отловить в режиме отладки.

Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...