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

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


gonzales

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

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

Помогите советом, как убить кнопку кликнув на нее. Создаю на скролбоксе динамический массив кнопок (наследники Trectangle). По нажатию (onClick) любой кнопки из массива весь массив должен уничтожиться. Естественно это приводит к ошибке. В VCL я бы использовал POSTMESSAGE но в firemonkey затрудняюсь ответить. На ум пока приходит только Таймер)))) Но это же жесть)))

Приложение кроссплатформенное, поэтому решение нужно соответствующее.

Заранее всем спасибо за советы. 

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

PS. Причем, что самое странное ошибка возникает не всегда, она плавающая, причем по какой-то неведомой причине возникает только при клике на третью кнопку))). Сама ошибка никак не сказывается на работоспособности программы, все продолжает работать корректно и больше ошибка не повторяется, но при перезапуске программы опять всплывает

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

MyControl.Release;

Это отложенное удаление, реализованное самой платформой.

Надо только не забывать после Release заNil-ить ссылку на объект в массиве. Ну и вместо массива лучше использовать дженериковский список.

Изменено пользователем kami
Ссылка на комментарий

Да, извиняюсь, я просто удалял компоненты в цикле

(Form1.RoomsScrollBox.Components[i]).Free;

А когда я написал 

(Form1.RoomsScrollBox.Components[i] as TRoom).Release;

То метод появился. Но это понятно у TComponent его нет, только у TObject. 

Но сути вопроса это не изменило, по Release компонент пропадает, но он еще в памяти, соответственно я не могу создать на его месте другой компонент с таким именем.

 

Вообще задача следующая, есть дерево, находясь на ветке этого дерева я визуализирую все имеющиеся подветки (TRectangle) в ScrollBox. При нажатии на подветку я очищаю весь ScrollBox и выстраиваю новую визуализацию. Может подскажете, как это более грамотно реализовать? 

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

соответственно я не могу создать на его месте другой компонент с таким именем.

Зачем вообще указывать имя компоненту, создаваемому в runtime? Они прекрасно живут и без этого, а для идентификации конкретного - есть куча свойств TagXXX

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

Зачем вообще указывать имя компоненту, создаваемому в runtime? Они прекрасно живут и без этого, а для идентификации конкретного - есть куча свойств TagXXX

Обалдеть, спасибо!!!!!!!

Вот изящное решение!!!

Действительно, все работает без всяких имен. Вот что значит привычка, всегда писал с присвоением имени)))) Даже не думал, что можно не указывать имя вообще!

 

Еще раз спасибо!

Ссылка на комментарий
  • 1 год спустя...

Метод Release объявлен "устаревшим" (10.2.3). Всех поздравляю. Взамен разработчики ничего не предлагают. Теперь корректно разрушить элемент по щелчку на нем не получится. Достаем костыли.

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

Метод Release объявлен

метод Release создавал новый поток для каждого удаления, что как бы не очень правильно. Я сделал костыль через список объектов на удаление + таймер

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

в XE8 как раз и было реализовано через помещение в объект TPurgatory. (удален из 10)

он как раз и помещал объект к себе в список и удалял "чуть позже" по таймеру (через 10 мс).

unit FMX.Types;

  type
  TPurgatory = class (TComponent)
  public const
    TimerInterval: Integer = 10;
  private
    FInstanceList: TList<Pointer>;
    FTimerHandle: TFMXHandle;
    FPlatformTimer: IFMXTimerService;
    procedure StartTimer;
    procedure StopTimer;
    procedure TimerProc;
    procedure UpdateTimer;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Clear;
    procedure Add(const Instance: TFmxObject);
    procedure Remove(const Instance: TFmxObject);
    function Contains(const Instance: TFmxObject): Boolean;
  end;

 

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

отдельный поток для "убийства" объекта? брутально!

вот как сделано в 10.2.3 :

procedure TFmxObject.Release;
begin
  if not (csDestroying in ComponentState) then
  begin
    if (Application <> nil) and (Action <> nil) then
      Application.UnregisterActionClient(Self);
    Parent := nil;
    TThread.ForceQueue(nil,
      procedure
      begin
        Self.DisposeOf;
      end);
  end;
end;

 

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

ну и тут поток. в чем вопрос?

они с этим Release уже мучаются хрен знает сколько и никак до ума не доведут.

основные-то моменты ясны. отцепить от Parent и тогда простой FreeAndNil() вполне подходит. Для ARC он внутри пустой.

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

FreeAndNil() не подойдет... проблема в том, что после вызова OnClick() далее еще происходят вызовы методов самого объекта (см. исходники FMX.Forms) и если разрушить объект на OnClick, то будет AV (не каждый раз - а как повезет... ).

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

ну и тут поток. в чем вопрос?

тут нет потока. forceQueue не использует создание потоков, оно пишет напрямую в структуры синхронизации.

Я у себя уже давно сделал хелпер с одним методом - Release. И его использую не получая сообщений от компилятора.

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

@kami все правильно написал. Используйте просто ForceQueue. А внутри либо отлинкуйте контрол от родителя и вызовите Free, либо брутально дергайте DisposeOf.

P.S. документация http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.ForceQueue

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

@kami все правильно написал. Используйте просто ForceQueue. А внутри либо отлинкуйте контрол от родителя и вызовите Free, либо брутально дергайте DisposeOf.

P.S. документация http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.ForceQueue

Намного проще оставить в покое метод Release.

Ссылка на комментарий
В 07.01.2019 в 17:45, slav_z сказал:

FreeAndNil() не подойдет... проблема в том, что после вызова OnClick() далее еще происходят вызовы методов самого объекта (см. исходники FMX.Forms) и если разрушить объект на OnClick, то будет AV (не каждый раз - а как повезет... ).

Я имел в виду - в конструкции TTask.Run - Synchronize конечно.
Ну и тот же FreeAndNil  в ForceQueue

Думаю в таком варианте будет все равнозначно.

Главное чтобы DisposeOf не вызывать руками в ARC. Мало ли там в недрах FMX еще кто его потрогать захочет... )))

Изменено пользователем krapotkin
Ссылка на комментарий

И еще в тему ForceQueue.

Как-то раз потребовалась мне конструкция типа "отложенное действие после отложенного действия". Дык вот, если сделать вот так:

TThread.ForceQueue(
  procedure
  begin
    SomeAction;
    ForceQueue(SomeAnotherAction);
  end);

то SomeAnotherAction выполнится сразу же вслед за SomeAction, а не на новом витке Application.Idle.
Всё дело в том, что выполнятель Queued-действий просто достает их из списка, пока не закончатся. Т.е. выполняется первый ForceQueue, а вложенный, как таковой, не выполняется: второе действие помещается в список, тут же достается из него и сразу же выполняется!

Как результат - при таком вызове де-факто получается срабатывает только первый ForceQueue, а вместо второго  выполняется прямой вызов действия.

Изменено пользователем kami
Ссылка на комментарий

но есть еще проблема:
Если сразу после Release попытаться создать элемент заново (TFrame), то будет ошибка дублирования имени компонента (старый компонент еще жив в списке компонентов родителя).

Поэтому кроме Parent := nil (убрать элемент с экрана) еще необходимо Name := '';

короче...  жуть какая-то.

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

Надо уметь мыслить в терминах асинхронного программирования. Тогда такие вещи не будут удивлять и не будет проблем.

Ссылка на комментарий
1 час назад, Brovin Yaroslav сказал:

Надо уметь мыслить в терминах асинхронного программирования. Тогда такие вещи не будут удивлять и не будет проблем.

теперь все понятно. спасибо.

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

Если сразу после Release попытаться создать элемент заново (TFrame), то будет ошибка дублирования имени компонента (старый компонент еще жив в списке компонентов родителя).

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

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

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

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

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

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

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

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

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

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

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

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