Delphi 2009以错误的顺序创建我的组件

时间:2011-03-02 10:47:26

标签: delphi components delphi-2009

三个组成部分,共同努力:
* CompA,一个TComponent后裔,一个了解许多事物并将事物捆绑在一起的策划组件
* CompB,一个TComponent后代,从它的CompA挖掘一些数据并对其进行处理。除其他外,还可以向CompC提供数据
- 已发布CompA类型的财产
* CompC,一个TComponent后代,一个TFrame后代绘图表面,可以在设计时设置为使用CompB作为数据提供者
- 已发布CompA类型的财产
- 已发布CompB类型的财产

我想我已经读过了,即使我不知道在哪里,Delphi的流引擎从.dfm读取所有组件并构建依赖图。然后,此图表用于按正确顺序创建所有组件。对于列出的组件,它应首先是CompA(因为它不使用其他组件),然后是CompB(它使用CompA并且必须在之后创建),最后是CompC,因为它具有其他组件类型的属性。

这不会发生。 CompC是在CompB之前创建的。如果我使用文本编辑器重新排列.dfm文件中的顺序,它可以工作。属性值不在任何构造函数中使用,仅在Loaded过程中使用。但是,无论dfm中组件的顺序如何,都必须有一种方法使其工作?

我现在已经连续两天撞墙了,我需要有人告诉我忘记了哪个关键字,或者我的设计有什么错误。

3 个答案:

答案 0 :(得分:6)

如果您的组件在很大程度上依赖于创建顺序,那么依赖于流机制总是会遇到麻烦。只需在表单/数据模块上添加或删除(另一个)组件就可以使您的订单失效。

为确保正确的创建顺序,最好在运行时创建它们。请注意,在运行时创建组件时,Loaded方法将被调用。您可能需要自己动手或将代码移动到创建组件后调用的某个init方法。

答案 1 :(得分:5)

我怀疑你的错是你正在尝试访问兄弟指针的setter上的其他对象属性,忘记在dfm加载阶段--runtime--你无法确定指向其他的指针组件所依赖的组件仍然有效,因为尚未创建其他组件。这是自Delphi 1以来的方式。

因此,您通常会将其他组件的状态(例如)读取到被覆盖的Loaded方法。

当流系统从其表单文件加载表单或数据模块时,它首先通过调用其构造函数构造表单组件,然后从表单文件中读取其属性值。 在读取所有组件的所有属性值之后,流系统按照创建组件的顺序调用每个组件的Loaded方法这使组件有机会初始化任何依赖于其他组件或其他部分的值的数据。     注意:所有对兄弟组件的引用都会在调用Loaded时解析。流式传输后, Loaded是第一个可以使用兄弟指针的地方

因此,通常在兄弟指针属性的setter方法上,您通常会检查此类型:

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来源,你会发现数百个这样的例子。

答案 2 :(得分:0)

您可以右键单击表单/数据模块,然后选择“创建订单”项。它将允许您选择“非可视”组件的创建顺序。视觉效果应遵循Tab键顺序,但我并不确定。

更新:我对标签顺序错了,但看起来可视化控件以Z顺序流式传输到.dfm。如果控件按照它们在.dfm中的顺序进行实例化,则可以使用Edit - >将前置/后置发送(或表单上下文菜单中的“控制”菜单)更改为z顺序。只要控件不重叠,您应该可以随意更改它。