Delphi 2009 создает мои компоненты в неправильном порядке - PullRequest
4 голосов
/ 02 марта 2011

Три компонента, работающие вместе:
* CompA, потомок TComponent, компонент mastermind, который знает много вещей и связывает их вместе
* CompB, потомок TComponent, добывает некоторые данные из своего CompA и обрабатывает их.Может, помимо прочего, предоставлять CompC данные для представления
- Имеет опубликованное свойство типа CompA
* CompC, потомок TComponent, поверхность рисования потомка TFrame, которую можно установить во время разработки, чтобы использовать CompB в качестве поставщика данных
- Имеет опубликованное свойство типа CompA
- Имеет опубликованное свойство типа CompB

Мне кажется, я помню, что прочитал, хотя не могу указать, где, что движок Delphi для потоковой передачи читает все компоненты из.dfm и строит граф зависимостей.Этот график затем используется для создания всех компонентов в правильном порядке.Для перечисленных компонентов это должен быть сначала CompA (поскольку он не использует ни один из других), затем CompB (он использует CompA и должен быть создан после) и, наконец, CompC, поскольку он обладает свойствами обоих других типов компонентов.

Этого не происходит.CompC создается до CompB.Если я изменить порядок в файле .dfm с помощью текстового редактора, он работает.Значения свойств не используются ни в каких конструкторах, только в загруженных процедурах.Но действительно ли должен быть способ заставить его работать независимо от порядка компонентов в dfm?

Я уже два дня бьюсь головой об стену, мне нужен кто-то, кто скажет мне, какиеКлючевое слово, которое я забыл, или какая у меня ошибка в дизайне.

Ответы [ 3 ]

6 голосов
/ 02 марта 2011

Я подозреваю, что вы виноваты в том, что вы пытаетесь получить доступ к свойствам других объектов в установщиках для родственных указателей , забывая, что на этапе загрузки dfm --runtime-- вы не можете быть уверены, что указатели на другие компонентыВаш компонент зависит от того, все еще действительны, потому что возможно, что другой компонент еще не создан.Это работает так с Delphi 1.

. Из-за этого вы обычно откладываете чтение состояния другого компонента (например) на переопределенный метод Loaded .

Когдапотоковая система загружает форму или модуль данных из своего файла формы, сначала она создает компонент формы, вызывая его конструктор, а затем считывает значения его свойств из файла формы. После считывания всех значений свойств для всех компонентов потоковая система вызывает методы Loaded для каждого компонента в том порядке, в котором были созданы компоненты . Это дает компонентам возможность инициализировать любые данные, которые зависят от значений других компонентов или других их частей .Примечание. Все ссылки на одноуровневые компоненты разрешаются ко времени вызова Loaded. Loaded - это первое место, где родственные указатели можно использовать после потоковой передачи.

Из-за этого обычно для метода установки для свойства указатель родного брата вы обычновыполните проверку этого типа:

procedure TMyComponent.SetDataSource(Value: TDataSource);
begin
  FDataSource := Value;
  //streaming in stage
  if not (csLoading in ComponentState) then
    ReadDataSourceProperties;
end;

procedure TMyComponent.Loaded;
begin
  ReadDataSourceProperties;
end;

Посмотрите на источник VCL, вы найдете сотни примеров этого.

6 голосов
/ 02 марта 2011

Если ваши компоненты сильно зависят от порядка создания, у вас всегда будут проблемы с использованием механизма потоковой передачи.Только одно добавление или удаление (n другого) компонента в модуле формы / данных может привести к тому, что ваш заказ будет выведен из строя.

Чтобы обеспечить надлежащий порядок создания, лучше создать их во время выполнения.Просто обратите внимание, что при создании компонентов во время выполнения метод Loaded будет вызываться , а не .Вам придется либо сделать это самостоятельно, либо переместить код в какой-либо метод init, который вы вызываете после создания компонентов.

0 голосов
/ 02 марта 2011

Вы можете щелкнуть правой кнопкой мыши форму / модуль данных и выбрать пункт «Порядок создания». Это позволит вам выбрать порядок создания «невизуальных» компонентов. Визуальные должны следовать за порядком табуляции, но я не совсем уверен в этом.

Обновление : Я ошибся в порядке табуляции, но похоже, что визуальные элементы управления передаются в .dfm в Z-порядке. Если элементы управления создаются в том порядке, в котором они находятся в формате .dfm, вы можете использовать Edit -> Bring to front / send to back (или меню Control в контекстном меню формы), чтобы изменить порядок z. Пока элементы управления не перекрываются, вы должны быть достаточно свободны, чтобы изменить его.

...