Delphi FireMonkey自定义可视化组件集成问题求助
开发了一个用于Delphi FireMonkey框架的可视化组件类,通过包安装后将组件添加到窗体,组件可视化显示正常,保存窗体无错误且.fmx文件内容正确,但切换RAD Studio的设计/代码标签或运行程序时,报错“can not find Class TMySpeedbutton”。
可复现问题的代码如下:
unit uMyVisualLayout; interface uses System.SysUtils, System.Classes, FMX.Types, FMX.Controls, FMX.Layouts, FMX.StdCtrls, FMX.Objects, FMX.Graphics; Type TMyImage = class(TImage) private FBackupImage: TBitmap; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; Type TMySpeedbutton = class(TSpeedButton) private FLabelText: TLabel; function GetNewText: String; procedure SetNewText(const Value: String); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; property NewText: String read GetNewText write SetNewText; end; Type TMyLayout = class(TLayout) private { Private-Deklarationen } Speedbutton1, Speedbutton2, Speedbutton3: TMySpeedbutton; TopFlowLayout: TFlowLayout; procedure ButtonClick(Sender: Tobject); protected { Protected-Deklarationen } public constructor Create(AOwner: TComponent); override; { Public-Deklarationen } published { Published-Deklarationen } end; procedure Register; implementation procedure Register; begin RegisterComponents('TestVisualComponent', [TMyLayout]); end; { TMyLayout } procedure TMyLayout.ButtonClick(Sender: Tobject); begin log.d(TSpeedButton(Sender).Name + ' Clicked!'); end; constructor TMyLayout.Create(AOwner: TComponent); begin inherited; TopFlowLayout := TFlowLayout.Create(self); TopFlowLayout.Parent := self; TopFlowLayout.Align := TAlignLayout.MostTop; Speedbutton1 := TMySpeedbutton.Create(self); Speedbutton1.Parent := TopFlowLayout; Speedbutton1.Align := TAlignLayout.Client; Speedbutton1.NewText := 'Speedbutton1'; Speedbutton1.OnClick := ButtonClick; Speedbutton2 := TMySpeedbutton.Create(self); Speedbutton2.Parent := TopFlowLayout; Speedbutton2.Align := TAlignLayout.Client; Speedbutton2.NewText := 'Speedbutton2'; Speedbutton2.OnClick := ButtonClick; Speedbutton3 := TMySpeedbutton.Create(self); Speedbutton3.Parent := TopFlowLayout; Speedbutton3.Align := TAlignLayout.Client; Speedbutton3.NewText := 'Speedbutton3'; Speedbutton3.OnClick := ButtonClick; end; { TMyImage } constructor TMyImage.Create(AOwner: TComponent); begin inherited; FBackupImage := TBitmap.Create; end; destructor TMyImage.Destroy; begin FBackupImage.Free; inherited; end; { TMySpeedbutton } constructor TMySpeedbutton.Create(AOwner: TComponent); begin inherited; FLabelText := TLabel.Create(self); FLabelText.Parent := self; FLabelText.Align := TAlignLayout.Client; end; destructor TMySpeedbutton.Destroy; begin FLabelText.Free; inherited; end; function TMySpeedbutton.GetNewText: String; begin Result := FLabelText.Text; end; procedure TMySpeedbutton.SetNewText(const Value: String); begin FLabelText.Text := Value; end; end.
问题原因
- 自定义组件未注册:仅注册了顶层组件
TMyLayout,但TMySpeedbutton作为TMyLayout动态创建的自定义组件,在FMX加载.fmx文件时,IDE和程序需要通过注册信息找到该类才能完成实例化,未注册会导致类找不到的错误。 - 流序列化依赖注册信息:FireMonkey的窗体流系统在解析.fmx内容时,会根据组件类名查找对应的注册类,未注册的自定义类无法被识别。
解决步骤
- 注册所有自定义组件:修改
Register过程,将TMySpeedbutton和TMyImage(若后续会用到)一并注册:
procedure Register; begin RegisterComponents('TestVisualComponent', [TMyLayout, TMySpeedbutton, TMyImage]); end;
- 为动态创建的组件设置Name属性:虽然不是强制要求,但为动态组件设置唯一的
Name有助于FMX流系统正确识别组件,避免潜在的序列化问题:
Speedbutton1 := TMySpeedbutton.Create(self); Speedbutton1.Name := 'Speedbutton1'; // 添加Name赋值 Speedbutton1.Parent := TopFlowLayout; // 其他两个按钮同理添加Name赋值
- 确认包的安装完整性:确保包含该单元的设计时包和运行时包已正确安装,且目标项目已引用运行时包(或选择静态编译该单元到项目中)。
内容的提问来源于stack exchange,提问作者fisi-pjm
相关产品推荐
相关产品推荐

