-
Есть компонент (Telement = class TComponent) который является свойством TСollectionItem
Для сохранение в DFM установлено SetSubComponent(True);
Но есть проблема в виду того что TСollectionItem не является компонентом не происходит вызов Loaded по завершению загрузки из DFM.
Собственно вопрос: Как внутри Telement узнать про то что загрузка завершена. Очень желательно обойтись только внутренними ресурсами. Имеется в виду что про окончание загрузки компонент должен знать сам. Вызов из Loaded формы не подходит.
Может можно как то подписаться на вызов Loaded? В classes есть некий GlobalLoaded и BeginGlobalLoading но как их правильно использовать не очень понятно.
Может кто что знает по этой теме?
-
Ещё раз по подробнее, а лучше с кодом.
Компонент является свойством элемента коллекции ?
Тогда вызовите самостоятельно Loaded для каждого элемента коллекции из Loaded основного компонента
-
>Компонент является свойством элемента коллекции ?
Да.
>Тогда вызовите самостоятельно Loaded для каждого элемента коллекции из Loaded основного компонента
Хотялось бы чтобы была независимость написнного мной класса. Т.е. чтобы он работал без дописания дополнительного кода. А то как то криво смотриться рекомендации что для корректной работы моего класса нужно будет дёргать его метод из чего то внешнего просто ради того чтобы он работал а не потому что это нужно пользователю :(
>Ещё раз по подробнее, а лучше с кодом.
Так не вопрос. Только вот код чего интересует? У меня же глюков нет. Всё работает штатно.
-
О том что вы где то в недрах одного компонента спрятали другой среда ничего не знает и естественно никакого Loaded не будет, если вы его не пошлёте самостоятельно. А рекомендации что нужно дёргать внутренний метод смотрятся вовсе не криво.
Как вы считаете должна ПО ДРУГОМУ работать Loaded ?
-
>Как вы считаете должна ПО ДРУГОМУ работать Loaded ?
Можно и на ты :)
Я хочу работать с Loaded не по другому а так же как она и работает в дельфи. Т.е. хотелось бы иметь возможность подписаться на получение Loaded. Причём этот функционал есть в TReader только вот он не доступен :(
Есть GlobalLoaded и BeginGlobalLoading но я не очень знаю для чего они и можно ли их дёргать. И прописываться в них.
-
Или возможно есть другие пути узнать о завершении загрузки.
-
Других путей нет. Вы придумали эту архитектуру. Среда не может обходить все возможные TPersistent, TList, array, приват свойства, в поисках того, кому бы ещё послать Loaded, да это и не логично. Неужели трудно организовать цикл ?
procedure TMyComp.Loaded;
var i: integer;
begin
inherited Loaded;
with MyCollection do
for i := 0 to Items.Count -1 do
if Assigned(Items[i].MyPropComponent) then Items[i].MyPropComponent.Loaded;
end;
-
Само собой не трудно. Но я хотел сделать отдельный компонент который бы без проблем встраивался в другие. Без написания дополнительного кода. Так же как это происходит с обычными компонентами.
Само собой среда не будет оповещать всех. Но ведь она могла бы оповещать тек кто попросит. Так же как это сделано с уведомлениями о удалении компонента например.
И даже есть подходящий список GlobalLoaded только вот я не очень понимаю при каких условиях он будет загружен и какие есть ограничения на добавление в него своих компонентов.
-
Что значит "встраивался в другие" ? В какой другой (НЕ СВОЙ) компонент вы можете его встроить ?
-
Как в какой? Я могу взять модуль и передать его соседу рядом. И очень хотелось бы чтобы он там работал вне зависимости от того прописал ли сосед волшебные строчки или забыл.
-
GlobalLoaded увы тоже не доступен. Ну или я не нашел как к нему достучаться :(
-
Короче сдался :(
Создал в парном компонете список в котором можно регистрироваться и запряг его вызывать Loaded всех кто в нём зарегистировался.
Парный компонент это комонент который точно будет в проекте использующем мой компонент.
Извращение однако... Но работает :)
-
То есть вы считаете, что кто-то сможет прицепить ваш ВНУТРЕННИЙ компонент к своему ВНЕШНЕМУ ? Тогда что же мешает вызвать LOADED ? Не получается с LOADED, попробуйте изменить логику так, чтобы нужные вам действия происходили в другом месте.
А вообще, разговор об абстракциях - сотрясение воздуха. Нет ни строчки кода, ни намёка, что вообще делает ваш компонент.
-
>То есть вы считаете, что кто-то сможет прицепить ваш ВНУТРЕННИЙ компонент к своему ВНЕШНЕМУ ?
Где я такое написал?
>Тогда что же мешает вызвать LOADED ?
Никто так и сделал.
>А вообще, разговор об абстракциях - сотрясение воздуха. Нет ни строчки кода, ни намёка, что вообще делает ваш компонент.
Компонент хранит список ссылок на существующеие компоненты. С сохранением этого списка в dfm через DefineProprty. Чтобы при чтении из dfm корректно восстановить ссылки нужно сделать FixUp по завершению загрузки.
Ещё раз спрашиваю код чего именно вас интересует??
-
>Компонент хранит список ссылок на существующие компоненты.
1. Зачем хранить список ссылок, если они и так есть в списке Формы ?
2. Что будут делать 10 компонентов в 10-ти элементах коллекции ? Десять раз Фиксить ?
3. Пытаюсь понять для чего это вообще нужно - ума не приложу. А раз непонятна цель, то и выбор средств тоже неясен. Может вообще не в LOADED дело ?
-
>1. Зачем хранить список ссылок, если они и так есть в списке Формы ?
Для использования в личных целях компонента. Т.е. ему не нужны все. Ему нужны некоторы например первый, пятый и десятый.
>2. Что будут делать 10 компонентов в 10-ти элементах коллекции ? Десять раз Фиксить ?
Не очень понял про какие 10 компонентов идёт речь? Какдлый список нужно фиксить отдельно. Если списков будет десять то само собой фикс для каждого.
>3. Пытаюсь понять для чего это вообще нужно - ума не приложу.
Компоненты отвечают за отрисовку данных для пользователя. Т.е. в дизайн тайме можно набрать список комопонентов которые будут отображать некие данные. Компоненты не визуальные типа Taction.
-
> в дизайн тайме можно набрать список компонентов
То есть, компоненты из списка принадлежат форме и сохраняются в DFM. Это значит, что Loaded каждого из них будет вызван дважды: один раз - автоматически, второй - Вашим кодом. Получается, что Вам делать ничего не нужно, все сработает само.
Или я чего-то не понял?
-
Не совсем.
Реализовывалась связь многие ко многим.
Соответственно:
Есть TElement
Есть TElementList
Они само собой принадлежат форме и сохраняются в DFM. При чтении само собой получают Loaded.
Но есть ещё много TElementCollection которые хранят только списки ссылок на те элементы которые есть в TElementList. И тоже сохраняет их в DFM но уже как имя компонентов. Так как TElementCollection является полем TCollectionItem то никакого Loaded ему не приходит и соответственно ссылки нельзя корректно востановить.
Пока сделал глобальный список в котором TElementList регистрирует себя как желающий получить Loaded. А TElementList в своём Loaded обходит этот список и вызывает Loaded всем загрузившимся.
По хорошему хотелось бы регистрироваться в списках TReader но не вышло :(
-
Чего-то я не понимаю, видимо.
> Есть TElement
> Есть TElementList
>
> Они само собой принадлежат форме и сохраняются в DFM. При
> чтении само собой получают Loaded.
Пока все нормально. Но тут же Вы пишете:
> сделал глобальный список в котором TElementList регистрирует
> себя как желающий получить Loaded.
Зачем нужна эта регистрация, если TElementList и без нее получает свой Loaded?
А в нем TElementList проходит по элементам коллекции и восстанавливает ссылки. Без всяких дополнительных списков.
-
Упс... Следует читать: Пока сделал глобальный список в котором TElementCollection регистрирует... далее по тексту.
-
>Юрий Зотов
У него в элементах коллекции хранятся компоненты, которые "должны" получать LOADED. Среда о них естественно не знает и LOADED для них не вызывает. А написать свой LOADED, как я предлагал в [6], он не хочет.
-
Почему не хочу? Я так и сделал.
-
> DimaBr © (06.10.14 14:33) [20]
А почему среда о них не знает? Если я правильно понял, то включение в элементы коллекции ссылок на эти компоненты (или их имен, неважно) делается в design-time. Значит, эти компоненты УЖЕ лежат на форме и, следовательно, каждый из них получит свой Loaded обычным путем.
-
Тут, по-моему, проблема другая. Вот положил я на форму компонент, создал элемент коллекции и включил в него имя этого компонента. А потом взял, да и переименовал этот компонент - а в элементе коллекции имя осталось старым. Или удалил этот компонент - а в элементе коллекции его имя осталось. В обоих случаях получим битую ссылку.
Чтобы такого безобразия не было, компонент должен знать все элементы коллекции, в которые он включен, а еще в компоненте надо перекрывать SetName, Notification и еще какой-то метод (не помню его названия, ну да не в этом суть). Значит, этот компонент уже не может быть любым, а может быть только специальным.
-
>Значит, этот компонент уже не может быть любым, а может быть только специальным.
Увы это так. С любым не вышло.
>Если я правильно понял, то включение в элементы коллекции ссылок на эти компоненты (или их имен, неважно) делается в design-time. Значит, эти компоненты УЖЕ лежат на форме и, следовательно, каждый из них получит свой Loaded обычным путем.
Так проблема не с самими компонентами а со списком который хранит на них ссылки. Так как список невизуальный ему ничего не приходит. А в дизайн тайме у него просто написан редактор.
-
> MegaVolt_old (07.10.14 12:00) [24]
> Так проблема не с самими компонентами а со списком который хранит на них
> ссылки. Так как список невизуальный ему ничего не приходит.
А ему и ничего и не надо. Этот список надо включить в компонент-менеджер, который получит свой законный Loaded, в нем пройдет по списку и разрешит все ссылки на рабочие компоненты. А заодно и пропишет себя в каждый рабочий компонент, чтобы те знали, кого уведомлять о своем переименовании/удалении (чтобы в итоге обновить список).
-
>Этот список надо включить в компонент-менеджер, который получит свой законный Loaded
Так и сделал :)
-
На сколько я понял, компоненты лежат не на форме а внутри коллекции хозяина.
-
Неа. [17] прочитай ещё раз.
-
Проблема не решена.
Form1.Loaded приходит раньше чем загружен весь проект. Т.е. например DataModul может быть не загружен вообще :(
-
Здрасте, приехали !!!
При чём здесь Form1.Loaded и DataModule ????
Datamodule может вообще никогда не загрузиться, если его создавать динамически.
На лицо пункт 3 из поста
[14]3. Пытаюсь понять для чего это вообще нужно - ума не приложу. А раз непонятна цель, то и выбор средств тоже неясен. Может вообще не в LOADED дело ?
-
Да чёрт с ним с динамическим созданием.
В DataModul лежит Контейнер с компонентами.
Форма должна восстановить ссылки на них. А DataModul ущё не создан.
Чтобы было понятнее привожу на примере Action:
Имеем:
_____________________
Unit1;
Uses Unit2;
...
Form1.Action:=DataModule3.FontEdit1; (само собой это настроено в дизайнере а не ручками прописано)
_____________________
Unit2:
ActionList1 который содержит FontEdit1;
_____________________
FixUp для Form1.Action дельфи делает сама. Причём в не зависимости от того что физически создаётся первее или форма или модуль.
В моём случае я его делаю сам.
Где правильно вызывать мой FixUp?
Пока сделал так:
1. Если первой создалась форма то FixUp вызывается в ActionList1.Loaded;
2. Если же первой создан модуль то никакой FixUp не нужен все компоненты уже созданы и связывание идёт во время чтения свойст из DFM.
Кривовато. Но работает.
Если иметь одно место из которого вызывался бы FuxUp по окончанию создания всех форм и модулей то можно было бы упростить и отказаться от 2.
-
Вы хотите, чтобы можно было зависимые друг от друга модули создавать в разном порядке и при этом ссылки на компоненты восстанавливались при загрузке модуля, от которого есть ссылки?
Скажите, чем вызвано подобное требование?
Не проще ли создавать требуемый модуль в нужном порядке?
-
>Вы хотите..........
Ага. Более того я это сделал как описано в [31]. Причём это же далает дельфи без малейших проблем. Чтобы убедиться создайте две зависимые формы и в dpr поменяйте местами Application.CreateForm....
>Скажите, чем вызвано подобное требование?
Тем что подобную перестановку допускает дельфи. И как следствие мой компонент должен точно так же это переносить.
>Не проще ли создавать требуемый модуль в нужном порядке?
У того кто пишет компоненту нету никакой возможности влиять на порядок создания форм и модулей. Повторюсь: Дельфи допускает создание проекта в любом порядке вне зависимости от того какие зависимости есть. Я скажу даже больше зависимости служат скорее для корректности написания программы а при создании формы уже не важно кто от кого зависит.
-
Что-то тут не так. Миллион раз писаны программы, в которых есть DataModule с DataSet'ами, и на эти DataSet'ы ссылается главная форма. И все прекрасно загружается без всяких дополнительных усилий.
-
>И все прекрасно загружается без всяких дополнительных усилий.
Ссылка на датасет у формы это поле? Типа TDataSet?
А у меня сассив таких полей. Дельфи не хочет массив автоматом фиксить.
-
С подобной проблемой сталкиваются наследники TDataSet при установке свойства Active. То есть в дизайнере установлено TSQL1.Active:=True;
А TSession находится в DataModule, который ещё не загрузился. Или, что ещё чаще, на той же форме, но ниже по тексту. Посмотрите, как устроен SetActive у TDataSet.
-
icWasya проблемы с одним полем нету. Есть проблема с массивом компонентов как поле.
-
Вы ошибаетесь, если думаете что без разницы в какой последовательности создавать формы и датамодули. Если это работает в дизайнере с датасетами (в последних версиях delphi), то это вовсе не значит что всё происходит так как вы видите на экране. В ранних версиях среды, открытие формы, без предварительного открытия датамодуля, приводило к тому, что ссылки на датасеты и прочие компоненты на датамодуле терялись. Поэтому я лично себя приучил открывать проекты строго в определённой последовательности, сначала датамодули, а затем формы. В нынешней среде (по крайней мере у меня хе2) при открытии формы, которая ссылается на датамодуль, последний создаётся автоматически, просто вы его не видите.
Итого.
Фиксить вручную ссылочные компонеты не нужно. Нужно менять идеологию вашего компонента, возможно вешать хак на нотификацию и фиксить не на LOADED, а INSERT формы.
-
>Вы ошибаетесь, если думаете что без разницы в какой последовательности создавать формы и датамодули.
Я не ошибаюсь а говорю про результаты изучения работы исходников D7 в них восстановление ссылок корректно работает при любом порядке создания форм и модулей.
-
>Фиксить вручную ссылочные компонеты не нужно.
Да можно и не вручную но боюсь чтобы дельфи сама пофиксила они должна получить PropInfo.
А вот существует ли оно для свойства типа массив я не знаю. И не нашел как его сделать. Буду благодарен за любые наводки.