You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi FireMonkey自定义可视化组件集成问题求助

问题排查:FireMonkey组件加载时提示“找不到TMySpeedbutton类”

开发了一个用于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内容时,会根据组件类名查找对应的注册类,未注册的自定义类无法被识别。

解决步骤

  1. 注册所有自定义组件:修改Register过程,将TMySpeedbutton和TMyImage(若后续会用到)一并注册:
procedure Register;
begin
  RegisterComponents('TestVisualComponent', [TMyLayout, TMySpeedbutton, TMyImage]);
end;
  1. 为动态创建的组件设置Name属性:虽然不是强制要求,但为动态组件设置唯一的Name有助于FMX流系统正确识别组件,避免潜在的序列化问题:
Speedbutton1 := TMySpeedbutton.Create(self);
Speedbutton1.Name := 'Speedbutton1'; // 添加Name赋值
Speedbutton1.Parent := TopFlowLayout;
// 其他两个按钮同理添加Name赋值
  1. 确认包的安装完整性:确保包含该单元的设计时包和运行时包已正确安装,且目标项目已引用运行时包(或选择静态编译该单元到项目中)。

内容的提问来源于stack exchange,提问作者fisi-pjm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 14:54:50