gonzales Опубликовано 18 января, 2017 Поделиться Опубликовано 18 января, 2017 Доброго времени суток! Помогите советом, как убить кнопку кликнув на нее. Создаю на скролбоксе динамический массив кнопок (наследники Trectangle). По нажатию (onClick) любой кнопки из массива весь массив должен уничтожиться. Естественно это приводит к ошибке. В VCL я бы использовал POSTMESSAGE но в firemonkey затрудняюсь ответить. На ум пока приходит только Таймер)))) Но это же жесть))) Приложение кроссплатформенное, поэтому решение нужно соответствующее. Заранее всем спасибо за советы. Цитата Ссылка на комментарий
gonzales Опубликовано 18 января, 2017 Автор Поделиться Опубликовано 18 января, 2017 PS. Причем, что самое странное ошибка возникает не всегда, она плавающая, причем по какой-то неведомой причине возникает только при клике на третью кнопку))). Сама ошибка никак не сказывается на работоспособности программы, все продолжает работать корректно и больше ошибка не повторяется, но при перезапуске программы опять всплывает Цитата Ссылка на комментарий
kami Опубликовано 18 января, 2017 Поделиться Опубликовано 18 января, 2017 (изменено) MyControl.Release; Это отложенное удаление, реализованное самой платформой. Надо только не забывать после Release заNil-ить ссылку на объект в массиве. Ну и вместо массива лучше использовать дженериковский список. Изменено 18 января, 2017 пользователем kami Brovin Yaroslav 1 Цитата Ссылка на комментарий
gonzales Опубликовано 18 января, 2017 Автор Поделиться Опубликовано 18 января, 2017 У TRectangle нет метода release.(( Цитата Ссылка на комментарий
kami Опубликовано 18 января, 2017 Поделиться Опубликовано 18 января, 2017 1 час назад, gonzales сказал: У TRectangle нет метода release.(( Он никуда не мог деться: RoschinSpb и Brovin Yaroslav 2 Цитата Ссылка на комментарий
gonzales Опубликовано 19 января, 2017 Автор Поделиться Опубликовано 19 января, 2017 Да, извиняюсь, я просто удалял компоненты в цикле (Form1.RoomsScrollBox.Components[i]).Free; А когда я написал (Form1.RoomsScrollBox.Components[i] as TRoom).Release; То метод появился. Но это понятно у TComponent его нет, только у TObject. Но сути вопроса это не изменило, по Release компонент пропадает, но он еще в памяти, соответственно я не могу создать на его месте другой компонент с таким именем. Вообще задача следующая, есть дерево, находясь на ветке этого дерева я визуализирую все имеющиеся подветки (TRectangle) в ScrollBox. При нажатии на подветку я очищаю весь ScrollBox и выстраиваю новую визуализацию. Может подскажете, как это более грамотно реализовать? Цитата Ссылка на комментарий
kami Опубликовано 19 января, 2017 Поделиться Опубликовано 19 января, 2017 1 минуту назад, gonzales сказал: соответственно я не могу создать на его месте другой компонент с таким именем. Зачем вообще указывать имя компоненту, создаваемому в runtime? Они прекрасно живут и без этого, а для идентификации конкретного - есть куча свойств TagXXX gonzales и Brovin Yaroslav 2 Цитата Ссылка на комментарий
gonzales Опубликовано 19 января, 2017 Автор Поделиться Опубликовано 19 января, 2017 6 минут назад, kami сказал: Зачем вообще указывать имя компоненту, создаваемому в runtime? Они прекрасно живут и без этого, а для идентификации конкретного - есть куча свойств TagXXX Обалдеть, спасибо!!!!!!! Вот изящное решение!!! Действительно, все работает без всяких имен. Вот что значит привычка, всегда писал с присвоением имени)))) Даже не думал, что можно не указывать имя вообще! Еще раз спасибо! Цитата Ссылка на комментарий
slav_z Опубликовано 3 января, 2019 Поделиться Опубликовано 3 января, 2019 Метод Release объявлен "устаревшим" (10.2.3). Всех поздравляю. Взамен разработчики ничего не предлагают. Теперь корректно разрушить элемент по щелчку на нем не получится. Достаем костыли. Цитата Ссылка на комментарий
Nick Peterson Опубликовано 3 января, 2019 Поделиться Опубликовано 3 января, 2019 2 часа назад, slav_z сказал: Метод Release объявлен метод Release создавал новый поток для каждого удаления, что как бы не очень правильно. Я сделал костыль через список объектов на удаление + таймер Цитата Ссылка на комментарий
slav_z Опубликовано 3 января, 2019 Поделиться Опубликовано 3 января, 2019 в 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; Ingalime 1 Цитата Ссылка на комментарий
FREEFAR Опубликовано 5 января, 2019 Поделиться Опубликовано 5 января, 2019 я убиваю в анонимном потоке слип(200) синхронизация (удаление) Цитата Ссылка на комментарий
slav_z Опубликовано 5 января, 2019 Поделиться Опубликовано 5 января, 2019 отдельный поток для "убийства" объекта? брутально! вот как сделано в 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; Цитата Ссылка на комментарий
krapotkin Опубликовано 7 января, 2019 Поделиться Опубликовано 7 января, 2019 ну и тут поток. в чем вопрос? они с этим Release уже мучаются хрен знает сколько и никак до ума не доведут. основные-то моменты ясны. отцепить от Parent и тогда простой FreeAndNil() вполне подходит. Для ARC он внутри пустой. Цитата Ссылка на комментарий
slav_z Опубликовано 7 января, 2019 Поделиться Опубликовано 7 января, 2019 FreeAndNil() не подойдет... проблема в том, что после вызова OnClick() далее еще происходят вызовы методов самого объекта (см. исходники FMX.Forms) и если разрушить объект на OnClick, то будет AV (не каждый раз - а как повезет... ). Цитата Ссылка на комментарий
kami Опубликовано 7 января, 2019 Поделиться Опубликовано 7 января, 2019 6 часов назад, krapotkin сказал: ну и тут поток. в чем вопрос? тут нет потока. forceQueue не использует создание потоков, оно пишет напрямую в структуры синхронизации. Я у себя уже давно сделал хелпер с одним методом - Release. И его использую не получая сообщений от компилятора. Brovin Yaroslav 1 Цитата Ссылка на комментарий
Администраторы Brovin Yaroslav Опубликовано 7 января, 2019 Администраторы Поделиться Опубликовано 7 января, 2019 @kami все правильно написал. Используйте просто ForceQueue. А внутри либо отлинкуйте контрол от родителя и вызовите Free, либо брутально дергайте DisposeOf. P.S. документация http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.ForceQueue Виталий Иванов и Yarpda 2 Цитата Ссылка на комментарий
slav_z Опубликовано 8 января, 2019 Поделиться Опубликовано 8 января, 2019 17 часов назад, Brovin Yaroslav сказал: @kami все правильно написал. Используйте просто ForceQueue. А внутри либо отлинкуйте контрол от родителя и вызовите Free, либо брутально дергайте DisposeOf. P.S. документация http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.ForceQueue Намного проще оставить в покое метод Release. Ingalime 1 Цитата Ссылка на комментарий
krapotkin Опубликовано 8 января, 2019 Поделиться Опубликовано 8 января, 2019 (изменено) В 07.01.2019 в 17:45, slav_z сказал: FreeAndNil() не подойдет... проблема в том, что после вызова OnClick() далее еще происходят вызовы методов самого объекта (см. исходники FMX.Forms) и если разрушить объект на OnClick, то будет AV (не каждый раз - а как повезет... ). Я имел в виду - в конструкции TTask.Run - Synchronize конечно. Ну и тот же FreeAndNil в ForceQueue Думаю в таком варианте будет все равнозначно. Главное чтобы DisposeOf не вызывать руками в ARC. Мало ли там в недрах FMX еще кто его потрогать захочет... ))) Изменено 8 января, 2019 пользователем krapotkin Цитата Ссылка на комментарий
kami Опубликовано 8 января, 2019 Поделиться Опубликовано 8 января, 2019 (изменено) И еще в тему ForceQueue. Как-то раз потребовалась мне конструкция типа "отложенное действие после отложенного действия". Дык вот, если сделать вот так: TThread.ForceQueue( procedure begin SomeAction; ForceQueue(SomeAnotherAction); end); то SomeAnotherAction выполнится сразу же вслед за SomeAction, а не на новом витке Application.Idle. Всё дело в том, что выполнятель Queued-действий просто достает их из списка, пока не закончатся. Т.е. выполняется первый ForceQueue, а вложенный, как таковой, не выполняется: второе действие помещается в список, тут же достается из него и сразу же выполняется! Как результат - при таком вызове де-факто получается срабатывает только первый ForceQueue, а вместо второго выполняется прямой вызов действия. Изменено 8 января, 2019 пользователем kami Цитата Ссылка на комментарий
slav_z Опубликовано 8 января, 2019 Поделиться Опубликовано 8 января, 2019 но есть еще проблема: Если сразу после Release попытаться создать элемент заново (TFrame), то будет ошибка дублирования имени компонента (старый компонент еще жив в списке компонентов родителя). Поэтому кроме Parent := nil (убрать элемент с экрана) еще необходимо Name := ''; короче... жуть какая-то. Цитата Ссылка на комментарий
Администраторы Brovin Yaroslav Опубликовано 8 января, 2019 Администраторы Поделиться Опубликовано 8 января, 2019 Надо уметь мыслить в терминах асинхронного программирования. Тогда такие вещи не будут удивлять и не будет проблем. krapotkin 1 Цитата Ссылка на комментарий
Администраторы Brovin Yaroslav Опубликовано 8 января, 2019 Администраторы Поделиться Опубликовано 8 января, 2019 P.S. И именно по этой причине, кстати, и был задепрекейчен Release. krapotkin 1 Цитата Ссылка на комментарий
slav_z Опубликовано 8 января, 2019 Поделиться Опубликовано 8 января, 2019 1 час назад, Brovin Yaroslav сказал: Надо уметь мыслить в терминах асинхронного программирования. Тогда такие вещи не будут удивлять и не будет проблем. теперь все понятно. спасибо. Barbanel и Yarpda 2 Цитата Ссылка на комментарий
kami Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 12 часов назад, slav_z сказал: Если сразу после Release попытаться создать элемент заново (TFrame), то будет ошибка дублирования имени компонента (старый компонент еще жив в списке компонентов родителя). помнится, отвечал уже кому-то на форуме. Для динамически создаваемых компонентов просто не указывайте имя. Не нужно оно им. Тогда эта проблема отпадает сама собой. Ingalime 1 Цитата Ссылка на комментарий
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.