三个组成部分,共同努力:
* CompA,一个TComponent后裔,一个了解许多事物并将事物捆绑在一起的策划组件
* CompB,一个TComponent后代,从它的CompA挖掘一些数据并对其进行处理。除其他外,还可以向CompC提供数据
- 已发布CompA类型的财产
* CompC,一个TComponent后代,一个TFrame后代绘图表面,可以在设计时设置为使用CompB作为数据提供者
- 已发布CompA类型的财产
- 已发布CompB类型的财产
我想我已经读过了,即使我不知道在哪里,Delphi的流引擎从.dfm读取所有组件并构建依赖图。然后,此图表用于按正确顺序创建所有组件。对于列出的组件,它应首先是CompA(因为它不使用其他组件),然后是CompB(它使用CompA并且必须在之后创建),最后是CompC,因为它具有其他组件类型的属性。
这不会发生。 CompC是在CompB之前创建的。如果我使用文本编辑器重新排列.dfm文件中的顺序,它可以工作。属性值不在任何构造函数中使用,仅在Loaded过程中使用。但是,无论dfm中组件的顺序如何,都必须有一种方法使其工作?
我现在已经连续两天撞墙了,我需要有人告诉我忘记了哪个关键字,或者我的设计有什么错误。
答案 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顺序。只要控件不重叠,您应该可以随意更改它。