slav_z Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 59 минут назад, kami сказал: помнится, отвечал уже кому-то на форуме. Для динамически создаваемых компонентов просто не указывайте имя. Не нужно оно им. Тогда эта проблема отпадает сама собой. я про TFrame.. конечно всяким TLable и т.п. имя назначать ни к чему... Фреймы получают имя в designtime и создаются (динамически) с этим именем. Цитата Ссылка на комментарий
#WAMACO Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 6 минут назад, slav_z сказал: я про TFrame.. конечно всяким TLable и т.п. имя назначать ни к чему... Фреймы получают имя в designtime и создаются (динамически) с этим именем. сделай "генератор имен" компонентов! и при создании назначай! Цитата Ссылка на комментарий
slav_z Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 4 минуты назад, #WAMACO сказал: сделай "генератор имен" компонентов! и при создании назначай! да нет смысла... это сложнее чем назначить пустое имя при создании. F:=TFrameClass.Create(Self); F.Name:=''; ... Цитата Ссылка на комментарий
krapotkin Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 С пустым именем может вообще не пустить. Точно помню... Цитата Ссылка на комментарий
slav_z Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 18 минут назад, krapotkin сказал: С пустым именем может вообще не пустить. Точно помню... напугать получилось... дай пять! да не... нет проблем с этим... Цитата Ссылка на комментарий
FREEFAR Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 2 часа назад, kami сказал: помнится, отвечал уже кому-то на форуме. Для динамически создаваемых компонентов просто не указывайте имя. Не нужно оно им. Тогда эта проблема отпадает сама собой. А разве если создавать по типу for i:=0 to 5 do begin a := tframe.create(self); end; не будет ошибки дублирования? по моему будет. по этой причине именовали := 'frame_'+i.toString; Цитата Ссылка на комментарий
krapotkin Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 будет. Цитата Ссылка на комментарий
slav_z Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 будет. но вместо := 'frame_'+i.toString; можно просто "обнулить" имя :=''; Цитата Ссылка на комментарий
Barbanel Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 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 работали. Ingalime 1 Цитата Ссылка на комментарий
kami Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 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; всё отрабатывает без проблем, никаких вопросов по именованию рантайм-компонентов не возникает. Цитата Ссылка на комментарий
slav_z Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 замени TFrame13.Create(nil) на TFrame13.Create(Self) только ради бога не спрашивай зачем... проверка на дублирование имени выполняется родителем... а он у тебя nil. #WAMACO 1 Цитата Ссылка на комментарий
kami Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 2 часа назад, slav_z сказал: проверка на дублирование имени выполняется родителем... а он у тебя nil Родитель-то как раз не nil. Владелец nil. Позвольте поинтересоваться, а какой профит помимо счастья обладания геморроем (который сам себе же и сделал) принесет создание компонента с указанием владельца? Единственный плюс, который мог бы быть - владелец при высвобождении себя уничтожает всё, чем он владеет. Но вот беда-то... родитель тоже это делает, причем - раньше. И благодаря подпискам на уведомления владелец узнаёт, что компонента, которым он владел, уже нет, т.е. попытки двойного уничтожения НЕ будет. Цитата Ссылка на комментарий
kami Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 Вы выискиваете какие-то обходные маневры, генерацию уникальных имен с привлечением guid, обнуление имени после создания... а на самом деле ничего из этих костылей не нужно. Barbanel 1 Цитата Ссылка на комментарий
slav_z Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 разработчики FMX по каким-то неведомым причинам сделали так, что визуальный контейнер при своем уничтожении так же разрушает и те компоненты, которые отображает (достаточно было просто обнулить Parent). такого никогда не было в VCL. это плохо и неправильно. это работа Owner а не Parent. Поробуйте создать элемент Create(Owner) и указать какой-нибудь посторонний Parent не принадлежащий Owner. При разрушении получите AV (сначала элемент будет разрушен Parent-ом а затем то же самое попытается сделать и Owner... нет там никаких нотификаций и подписок). я постараюсь далее не вступить в спор... но ничего не обещаю... Цитата Ссылка на комментарий
FREEFAR Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 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; всё отрабатывает без проблем, никаких вопросов по именованию рантайм-компонентов не возникает. Откуда узнал про религию дядя? Цитата Ссылка на комментарий
kami Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 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; Что я делаю не так? Цитата Ссылка на комментарий
kami Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 6 минут назад, FREEFAR сказал: Откуда узнал про религию дядя? Предположил на основании твоего вывода " не будет ошибки дублирования? по моему будет ", который проверяется и опровергается за 2 минуты. В результате вместо того, чтобы понять откуда ноги растут у ошибки дублирования имен - вы имеете костыли типа "по этой причине именовали := 'frame_'+i.toString; " Цитата Ссылка на комментарий
kami Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 Upd. Нет, похоже в fmx механизм FreeNotification не используется для уничтожения. Но это не мешает всему хозяйству уничтожаться корректно, какие бы родители с владельцами ни указывались Цитата Ссылка на комментарий
FREEFAR Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 6 минут назад, kami сказал: Предположил на основании твоего вывода " не будет ошибки дублирования? по моему будет ", который проверяется и опровергается за 2 минуты. В результате вместо того, чтобы понять откуда ноги растут у ошибки дублирования имен - вы имеете костыли типа "по этой причине именовали := 'frame_'+i.toString; " Предполагай по сути вопроса. А не отвлекаясь на офТоп. Или там в Питере культуре особо не учат? Или тебя ранило походу где-то, чем-то, как-то. Всем успел накидать я смотрю Цитата Ссылка на комментарий
RoschinSpb Опубликовано 9 января, 2019 Поделиться Опубликовано 9 января, 2019 Зря Вы TPurgatory угробили Простой пример: при потере фокуса закрывается всплывающее меню и разрушается всплывающая форма с этим меню, на OnClick всплывающего меню повешен обработчик, в обработчике возникает исключение которое приводит к появлению окошка с сообщением об ошибке появление окна с сообщением об ошибке закрывает и разрушает контекстное меню получается внутри метода объекта мы совершенно незаметно для себя уничтожили этот объект и на выходе из обработчика OnClick мы уже попадаем ... куда? В код разрушенного объекта. Может там остались старые данные и всё отработает нормально, а может там уже данные другого объекта, или еще какой мусор и приложение аварийно выкидывается из памяти. Как оно в итоге получится зависит от везения и фазы луны. Подобные ситуации могут возникнуть и в других, менее очевидных случаях. Так что будьте бдительны. Цитата Ссылка на комментарий
Nick Peterson Опубликовано 10 января, 2019 Поделиться Опубликовано 10 января, 2019 Да тут баг на баге сидит и погоняет Вот еще в духе этой темы: грид, лайвбиндинг.В Grid1HeaderClick выполняем обновление запроса (например, для сортировки). После этого форма перестает реагировать на мышь)) Уже впадлу багрепорты писать, штук 15 настрочил наверное а то и больше Решил пока через таймер... Цитата Ссылка на комментарий
kami Опубликовано 10 января, 2019 Поделиться Опубликовано 10 января, 2019 7 часов назад, FREEFAR сказал: Предполагай по сути вопроса. А не отвлекаясь на офТоп. Или там в Питере культуре особо не учат? Или тебя ранило походу где-то, чем-то, как-то. Всем успел накидать я смотрю Понаехавших - нет, не учат. Раненых особенно. Тебе эпитеты тоже подобрать? По сути вопроса? Как ты говоришь "накидывание" возникло от того, что для решения не самого сложного вопроса здесь озвучены (в том числе -тобой) рекомендации и выводы, от которых потом сложно не удивляться - откуда столько говнокода в экосистеме Делфи? Да вот отсюда, из таких топиков на форумах, которые неокрепшие (да и окрепшие) умы впитывают и несут потом в массы. Удивительно, что еще не затронули "уникальное имя нужно, потому что по нему потом будем искать этот компонент"... Цитата Ссылка на комментарий
Администраторы Brovin Yaroslav Опубликовано 10 января, 2019 Администраторы Поделиться Опубликовано 10 января, 2019 13 часов назад, slav_z сказал: Поробуйте создать элемент Create(Owner) и указать какой-нибудь посторонний Parent не принадлежащий Owner. При разрушении получите AV (сначала элемент будет разрушен Parent-ом а затем то же самое попытается сделать и Owner... нет там никаких нотификаций и подписок). А есть вообще понимание: Что такое Овнер для компонентов в делфи? Какую роль он играет в дизайнере и в рантайме? Цитата Ссылка на комментарий
Barbanel Опубликовано 10 января, 2019 Поделиться Опубликовано 10 января, 2019 13 часов назад, kami сказал: Вы выискиваете какие-то обходные маневры, генерацию уникальных имен с привлечением guid, обнуление имени после создания... а на самом деле ничего из этих костылей не нужно. Мой шеф любил говорить: -Мы сами создаем себе проблемы, а потом героически их преодолеваем. Штука с GUID была шуткой, я видимо должен был был это указать))))) Цитата Ссылка на комментарий
RoschinSpb Опубликовано 10 января, 2019 Поделиться Опубликовано 10 января, 2019 Не ссоритесь девочки пож. В 18.01.2017 в 17:57, gonzales сказал: Доброго времени суток! Помогите советом, как убить кнопку кликнув на нее... Возвращаясь к сути вопроса. Основная сложность тут в том, что в Delphi нельзя разрушать экземпляр класса внутри метода этого класса за исключением тех случаев, когда метод использует только для разрушения Free, DisposeOf. Почему так, а не иначе, какие есть исключения и почему "уменяфсёработает" объяснять долго, поэтому в первом приближении предлагаю принять это за аксиому. Обработчики событий OnClick и пр. вызываются из методов классов, так что разрушать контрол внутри события нельзя от слова совсем. Кроме очевидных случаев типа Self.DisposeOf существуют более запутанные варианты, когда к примеру закрывает и разрушается форма, что приводит к разрушению всех дочерних контролов. Образно говоря, самоубийства строго запрещены, но не запрещено нанимать киллера и в качестве жертвы указывать себя. Т.е. должен быть некий другой (глобальный) объект который будет разрушать объекты, которые хотели бы самоубицо. Реализацию такого объекта можете придумать сами, или использовать TPurgatory (чистилище, в католическом учении — промежуточное место между раем и адом). Но чтобы убедиться в правильности работы можно создать своего наследника TButton в котором перекрыть деструктор и поставить в нем точку останова. При запуске в режиме отладки посмотрите стек вызова деструктора (надо быть внимательным, он может быть длиннющим), ни где в этом стеке не должно быть метода разрушаемого экземпляра. Если в Вы нашли метод разрушаемого объекта (за исключением вышеуказанных), то Ваш способ удаления работает не правильно и с некоторой долей вероятности будет приводить к AV и другим "неприятностям" которые почти невозможно отловить в режиме отладки. kami, Tumaso, #WAMACO и 2 других 4 1 Цитата Ссылка на комментарий
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.