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

如何在TMS WEB Core中使用GetClass动态创建TWebFrame?

问题描述

静态创建并加载TWebFrame到窗体的函数运行正常,但需要根据类名字符串动态创建组件。尝试用GetClass实现的代码编译通过,但运行时调用LoadFromForm出现Uncaught TypeError: Cannot read properties of null (reading 'appendChild')错误,且已在帧的.pas文件中注册TFrame_Home类。因需创建大量帧,不想硬编码,求正确的动态创建方法。

原静态创建代码:

procedure LoadHomePage();
var
  FramePage: TWebFrame;
begin
  FramePage := TFrame_Home.Create(Self);

  FramePage.Name := 'layHome';
  FramePage.Visible := False;
  FramePage.Parent := LayoutContainer;
  FramePage.Align := alClient;
  FramePage.LoadFromForm;
end;

尝试的动态创建代码:

procedure LoadHomePageDynamically();
var
  FrameClass: TPersistentClass;
  FramePage: TWebFrame;
begin
  FrameClass := GetClass('TFrame_Home');
  FramePage := TWebFrame(FrameClass.Create);

  FramePage.Name := 'layHome';
  FramePage.Visible := False;
  FramePage.Parent := LayoutContainer;
  FramePage.Align := alClient;
  FramePage.LoadFromForm;
end;
解决方法

1. 核心问题:创建组件时未传入Owner参数

静态代码中TFrame_Home.Create(Self)传入了Owner(Self),但动态代码里FrameClass.Create无参数调用,导致组件初始化时缺少必要的上下文关联,最终引发DOM操作的空指针错误。

2. 修正后的动态创建代码

procedure LoadHomePageDynamically();
var
  FrameClass: TWebFrameClass; // 改用TWebFrameClass类型,避免强制类型转换风险
  FramePage: TWebFrame;
begin
  // 获取注册的类,确保类已正确注册且对应单元被引用
  FrameClass := TWebFrameClass(GetClass('TFrame_Home'));
  if not Assigned(FrameClass) then
    raise Exception.CreateFmt('类 %s 未注册或未引用对应单元', ['TFrame_Home']);

  // 创建组件时传入Owner参数,匹配静态代码的初始化逻辑
  FramePage := FrameClass.Create(Self);

  // 后续属性设置与加载逻辑保持不变
  FramePage.Name := 'layHome';
  FramePage.Visible := False;
  FramePage.Parent := LayoutContainer;
  FramePage.Align := alClient;
  FramePage.LoadFromForm;
end;

3. 确保类注册和单元引用正确

  • 必须在TFrame_Home所在的.pas文件中添加注册代码:
    initialization
      RegisterClass(TFrame_Home);
    
  • 确保包含TFrame_Home的单元已被主窗体单元引用,否则GetClass无法定位到该类。

4. 可选:RTTI方式创建(适用于复杂场景)

如果需要更灵活的类型创建,可通过RTTI实现:

uses
  System.Rtti;

procedure LoadHomePageDynamically();
var
  RttiContext: TRttiContext;
  RttiType: TRttiType;
  ConstructorMethod: TRttiMethod;
  FramePage: TWebFrame;
begin
  RttiContext := TRttiContext.Create;
  try
    // 需指定类的完整命名空间
    RttiType := RttiContext.FindType('你的命名空间.TFrame_Home');
    if not Assigned(RttiType) then
      raise Exception.Create('未找到目标类');

    ConstructorMethod := RttiType.GetMethod('Create');
    if not Assigned(ConstructorMethod) then
      raise Exception.Create('未找到合适的构造函数');

    // 调用构造函数并传入Owner参数
    FramePage := ConstructorMethod.Invoke(RttiType.AsInstance.MetaclassType, [Self]).AsType<TWebFrame>;

    // 属性设置与加载逻辑
    FramePage.Name := 'layHome';
    FramePage.Visible := False;
    FramePage.Parent := LayoutContainer;
    FramePage.Align := alClient;
    FramePage.LoadFromForm;
  finally
    RttiContext.Free;
  end;
end;

内容的提问来源于stack exchange,提问作者Shaun Roselt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 08:16:02