集合编辑器未针对 TPersistent 属性中的 TCollection 属性打开

2023-12-07

我有我的自定义集合属性,当它是我的组件的直接成员时,它工作得很好。

但我想将集合属性移动到组件内的 TPersistent 属性。现在问题来了,它不起作用:双击对象检查器中的集合属性通常会打开集合编辑器,但现在不再这样了。

首先 - 我应该将什么传递给 Persistent 属性的构造函数?

TMyCollection = class(TCollection)
  constructor Create(AOwner: TComponent); // TMyCollection constuctor
  ...

我无法通过Self,那么我是否应该通过我执着的主人呢?

constructor TMyPersistent.Create(AOwner: TComponent);
begin
  inherited Create;
  fOwner := AOwner;
  fMyCollection := TMyCollection.Create(AOwner); // hmmm... doesn't make sense
end;

我想我错过了一些东西。如果需要更多代码,请评论这篇文章。

Da visualizationz


TCollection 的构造函数不需要 TComponent,而是 TCollectionItemClass。

您的集合现在是 TPersistent 属性的成员,而不是组件的直接成员,对于构造函数来说没有什么区别。


Update

不同之处在于所有权,但在 TPersistent 级别,应该通过正确实现来管理GetOwner:

GetOwner 返回对象的所有者。 GetNamePath 方法使用 GetOwner 来查找持久对象的所有者。 TPersistent 中引入了 GetNamePath 和 GetOwner,因此诸如集合之类的后代可以出现在对象检查器中。

您必须告诉 IDE 您的 TCollection 属性由 TPersistent 属性拥有,而 TPersistent 属性又由组件拥有。

您正在使用的教程关于此实现有几个错误:

  • 集合的所有者被声明为 TComponent,它应该是 TPersistent,
  • GetOwner 没有为 TPersistent 属性类实现,并且
  • The fix本教程末尾所示的说明 TPersistent 属性应该从 TComponent 继承,这是完全错误的;或者更好地说:是不实现 GetOwner 的解决方法。

它应该是这样的:

unit MyComponent;

interface

uses
  Classes, SysUtils;

type
  TMyCollectionItem = class(TCollectionItem)
  private
    FStringProp: String;
  protected
    function GetDisplayName: String; override;
  public
    procedure Assign(Source: TPersistent); override;
  published
    property StringProp: String read FStringProp write FStringProp;
  end;

  TMyCollection = class(TCollection)
  private
    FOwner: TPersistent;
    function GetItem(Index: Integer): TMyCollectionItem;
    procedure SetItem(Index: Integer; Value: TMyCollectionItem);
  protected
    function GetOwner: TPersistent; override;
  public
    constructor Create(AOwner: TPersistent);
    function Add: TMyCollectionItem;
    function Insert(Index: Integer): TMyCollectionItem;
    property Items[Index: Integer]: TMyCollectionItem read GetItem
      write SetItem;
  end;

  TMyPersistent = class(TPersistent)
  private
    FOwner: TPersistent;
    FCollectionProp: TMyCollection;
    procedure SetCollectionProp(Value: TMyCollection);
  protected
    function GetOwner: TPersistent; override;
  public
    procedure Assign(Source: TPersistent); override;
    constructor Create(AOwner: TPersistent);
    destructor Destroy; override;
  published
    property CollectionProp: TMyCollection read FCollectionProp
      write SetCollectionProp;
  end;

  TMyComponent = class(TComponent)
  private
    FPersistentProp: TMyPersistent;
    procedure SetPersistentProp(Value: TMyPersistent);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property PersistentProp: TMyPersistent read FPersistentProp
      write SetPersistentProp;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TMyComponent]);
end;

{ TMyCollectionItem }

procedure TMyCollectionItem.Assign(Source: TPersistent);
begin
  if Source is TMyCollectionItem then
    FStringProp := TMyCollectionItem(Source).FStringProp
  else
    inherited Assign(Source);
end;

function TMyCollectionItem.GetDisplayName: String;
begin
  Result := Format('Item %d',[Index]);
end;

{ TMyCollection }

function TMyCollection.Add: TMyCollectionItem;
begin
  Result := TMyCollectionItem(inherited Add);
end;

constructor TMyCollection.Create(AOwner: TPersistent);
begin
  inherited Create(TMyCollectionItem);
  FOwner := AOwner;
end;

function TMyCollection.GetItem(Index: Integer): TMyCollectionItem;
begin
  Result := TMyCollectionItem(inherited GetItem(Index));
end;

function TMyCollection.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

function TMyCollection.Insert(Index: Integer): TMyCollectionItem;
begin
  Result := TMyCollectionItem(inherited Insert(Index));
end;

procedure TMyCollection.SetItem(Index: Integer; Value: TMyCollectionItem);
begin
  inherited SetItem(Index, Value);
end;

{ TMyPersistent }

procedure TMyPersistent.Assign(Source: TPersistent);
begin
  if Source is TMyPersistent then
    CollectionProp := TMyPersistent(Source).FCollectionProp
  else
    inherited Assign(Source);
end;

constructor TMyPersistent.Create(AOwner: TPersistent);
begin
  inherited Create;
  FOwner := AOwner;
  FCollectionProp := TMyCollection.Create(Self);
end;

destructor TMyPersistent.Destroy;
begin
  FCollectionProp.Free;
  inherited Destroy;
end;

function TMyPersistent.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

procedure TMyPersistent.SetCollectionProp(Value: TMyCollection);
begin
  FCollectionProp.Assign(Value);
end;

{ TMyComponent }

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FPersistentProp := TMyPersistent.Create(Self);
end;

destructor TMyComponent.Destroy;
begin
  FPersistentProp.Free;
  inherited Destroy;
end;

procedure TMyComponent.SetPersistentProp(Value: TMyPersistent);
begin
  FPersistentProp.Assign(Value);
end;

end.

但我可以说你也可以继承TOwnedCollection,这使得 TMyCollection 的使用和声明更加简单:

  TMyCollection = class(TOwnedCollection)
  private
    function GetItem(Index: Integer): TMyCollectionItem;
    procedure SetItem(Index: Integer; Value: TMyCollectionItem);
  public
    function Add: TMyCollectionItem;
    function Insert(Index: Integer): TMyCollectionItem;
    property Items[Index: Integer]: TMyCollectionItem read GetItem
      write SetItem;
  end;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

集合编辑器未针对 TPersistent 属性中的 TCollection 属性打开 的相关文章

  • Android中如何检测程序的终止?

    当 Windows 程序终止时 它会调用事件处理程序 例如 OnClose OnDestroy 和析构函数 Destroy 当我想保存一些 INI 设置时 这些地方就是我要保存的地方 我为所有这些事件编写了事件处理程序 但当我终止程序时它们
  • VirtualStringTree 正确/推荐使用

    我已经使用 virtualstringtree 一段时间了 我将它用于两个不同的用途 第一个是用于选择 显示数据的普通树 第二个是作为网格来显示 SQL 语句的输出 我加载到树中的所有数据都来自数据库 对于树示例 我有一个 ParentId
  • 在 ADO 查询 (mysql/MyConnector) 中使用参数

    今天我下载并安装了 MyConnector 这样我就可以通过 ADO 使用 Mysql 一切都安装好了 我可以与 ODBC 连接并从我的 delphi 环境进行连接 当我在运行时构建查询时 我收到一条错误消息 项目 Project1 exe
  • Delphi XE5 FireDAC 错误:无法加载供应商库 [libmysql.dll 或 libmysqld.dll]

    我在 Windows 7 64 位上使用 Delphi XE5 只是尝试 FireDAC 组件 我正在使用一个 TFDConnection 组件连接到本地 MySQL 数据库 v5 6 15 我已经将 libmysql dll 32位 v5
  • 构建机器是否需要单独的 Delphi XE4 许可证?

    用于通过以下方式构建应用程序dcc32在构建服务器上我可以使用 Delphi Trial 这种方法的许可证没有任何问题 现在 我将通过以下方式在 TeamCity 上构建 Delphi XE4 应用程序msbuild 我是否需要拥有构建机器
  • 使用 IOmniTaskControl/TOmniWorker 时等待 Invoke 完成

    我使用 TOmniWorker 创建了 IOmniTaskControl 以便我可以定期在特定线程上运行代码块 因此 我将根据需要在此 IOmniTaskControl 上调用 Invoke 当我这样做时 有时需要等待与该工作相关的执行完成
  • 如何在Delphi中实现人工神经网络? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想要一个人工神经网络 42 个输入神经元 168 个隐藏神经元 7个输出神经元 这个网络就是玩 连四子 的游戏 每场比赛结束时 网络
  • 当 datasnap 服务器中的用户授权失败时,是否可以更改响应代码?

    当用户授权失败时 是否可以更改 DataSnap Delphi XE3 服务器中的 HTTP 响应代码 目前正在回归HTTP 1 1 500 内部服务器错误 这可能发生在许多其他场景中 并且无助于描述问题 按照同样的想法 是否可以更改默认的
  • 如何使用 VCL 类的接口 - 第 2 部分 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 继续我之前关于使用 VCL 接口的调
  • 如何处理第三方库中的警告/提示?

    我们使用 FastReport 来生成报告 事实上 我们为访问源代码付费 我们目前使用的是FastReport的最新稳定版本 虽然它对于我们的生产来说足够稳定 但每当我编译时 我都会看到以下内容 dcc32 Hint fs iinirtti
  • 在 Delphi 中,我的 DLL 中是否必须分配函数的返回 pchar

    我有一个 DLL 其中有一个返回 pchar 的函数 以避免必须使用 borlndmm 我最初所做的是将字符串转换为 pchar 并返回 Result pChar SomeFuncThatReturnsString 但 90 的情况下我都能
  • 是否有适用于 >= Delphi 2007 的 Delphi 混淆器

    我曾经使用 Pythia 来混淆我的 D6 程序 但 Pythia 似乎不再适用于我的 D2007 这是 Pythia 的链接 自 2007 年初以来没有更新 http www the interweb com serendipity in
  • XE2 中的 COM 是否损坏?我该如何解决它?

    Update XE2 Update 2 修复了下述错误 下面的程序是从实际程序中截取的 在 XE2 中失败并出现异常 这是 2010 年的回归 我没有 XE 来测试 但我希望该程序在 XE 上运行良好 感谢 Primo 确认代码在 XE 上
  • 在 Delphi 中强制非阻塞临时提示窗口

    我一直在寻找 但找不到解决方案 所以我想也许我应该简单地发布它 这是我想要在 Delphi 2009 中做的事情 在我的应用程序中的某个时刻 我想向用户显示一条消息 这应该是正常的提示窗口 在正常应用程序定义的提示暂停后自动消失 并带有自定
  • Delphi 如何与 Active Directory 集成?

    我们需要使用 Delphi 7 验证 Microsoft Active Directory 上的用户 最好的方法是什么 我们可以有两种情况 用户输入其网络用户名和密码 其中用户名可能包括域 然后我们检查活动目录是否是有效的活动用户 或者我们
  • 有什么办法可以将2个数组添加到一个数组中吗?

    有没有一种简单通用的方法可以将两个数组添加到一个数组中 在下面的情况下 不可能简单地使用C A B陈述 我想避免每次都为它制定算法 TPerson record Birthday Tdate Name Surname string end
  • 如何更改 Chromium 组件的默认背景颜色?

    I use TChromium http code google com p delphichromiumembedded 我分配AWebPageAsString这是一个带有灰色背景颜色的静态 HTML 页面 FBrowser TChrom
  • Delphi 7,加载PNG到TImage

    只是想加载 PNG 尝试使用适用于其他格式的 OleGraphic 来使用我的 LoadPic 但在 PNG 上失败 目标是将图像复制到隐藏位图 然后将其屏蔽并复制到可见的工作图像画布 如果 CopyRect 不这样做 请随意提出其他建议
  • ADODB 组件导致 Win7/Server 2008 上的访问冲突

    我有一段用 Delphi 2005 编写的代码 用于在 LDAP 中搜索用户的特定属性 当在 Windows 7 或 Server 2008 上运行时 我遇到访问冲突 但在 XP 或 2003 上则没有 Function IsSSOUser
  • 错误:使用 Microsoft WebService.dll 通过 Delphi7 规范化 XML

    我正在使用 Delphi7 修改旧项目以添加使用证书和签名 经过一番搜索后我发现XML 规范化函数 https learn microsoft com en us previous versions dd815358 v vs 85 但我无

随机推荐

  • 获取一系列待处理的承诺

    var arr 1 2 3 4 5 6 67 8 10 function f1 return arr map function member console log member return Promise resolve member
  • Angular 6 在两个不相关的组件之间传递数据

    我有课程详细信息组件 其中包含来自后端应用程序的数据 名为课程 我想将该数据传递给与该组件无关的另一个组件 课程播放 我想在这两个组件中显示从后端获得的相同数据 这是相关文件 应用程序路由模块 import NgModule from an
  • 批处理文件中的字符串替换

    我们可以使用以下命令替换批处理文件中的字符串 set str jump over the chair set str str chair table 这些行工作正常 并将字符串 jump over the chair 更改为 jump ov
  • Google 地图 API 错误:此 API 密钥无权使用此服务或 API。地点 API 错误:ApiTargetBlockedMapError

    我开始从我使用的 CMS 内的 Google 地图小部件收到此错误 This API key is not authorized to use this service or API Places API error ApiTargetBl
  • 在 Python 中生成 CSR

    我正在尝试在 Python 中生成 CSR 而不使用 OpenSSL 如果有人能指出正确的方向 我将非常感激 我假设你不想使用命令行 openssl 本身 Python 库就可以了 这是我编写的用于创建 CSR 的辅助函数 它从生成的密钥对
  • ConvertTimeFromUTC,处理澳大利亚夏令时

    我有以下代码 我有一位位于澳大利亚堪培拉的客户 它们通常是 UTC 10 但现在处于 DST 所以是 UTC 11 奇怪的是 当我运行此代码时 它没有考虑 DST 我认为 ConvertTimeFromUTC 可以处理 DST 我正在路过E
  • 使用 Xcode、Swift3 的 iOS Rich Push 通知但无法获取图像

    我正在尝试使用 Xcode Swift3 创建 iOS 丰富推送通知 我已经使用 php 的curl 命令确定推送通知 主题 正文 但我无法创建引用的丰富推送通知在本文件中 我添加了通知服务扩展 如下所示 File New Target N
  • JTextArea 中的行

    有没有可靠的方法来计算 JTextArea 中字符串如何划分为行 我有一个固定宽度的 JTextArea 当它被填充时 会添加一个新行并垂直扩展 现在 我需要确切地知道哪些字符位于哪一行 我可以使用字体规格来添加单个字符宽度 但我不知道这是
  • 如何对表中特定数量的行进行着色?

    如何仅对特定数量的行进行着色 这里我的显示屏只有前 7 行是白色的 其余的是灰色的 我想要 7 条白色线 7 条灰色线 7 条白色线 7 条灰色线等等 你可以尝试这样的事情 table gt span height 20px width 2
  • 将 php 变量添加到 css 语句中!

    我想在我的 css 样式声明中包含以下内容 是否可以
  • 如果表2中不存在,如何插入到表1中?

    我是mysql新手 如果 table2 中不存在记录 则将记录插入到 table1 时出现问题 我有 2 个表 table1 和 table2 其形式为 table1 dep id start stop modified deleted 1
  • 是否可以在Python中创建特定目录的快捷方式?

    我查了一下 inetrnet 但没有发现任何相关内容 所以我在这里问 是否可以使用 python 创建文件的快捷方式并将其放入我选择的特定目录中 例如 我在 C 中有一个名为 EXAMPLE 的文件夹 我想自动创建谷歌浏览器的快捷方式并将其
  • 我可以序列化 ruby​​ Digest::SHA1 实例对象吗?

    大家好 我正在 ruby sinatra 中重新实现现有的自定义文件上传服务 并使用 redis 作为后备存储 客户 计算 SHA1 哈希并启动上传 上传最多 64K 块直至完成 服务器 将块附加到文件 计算完整文件的 SHA1 哈希值以验
  • 在 Ansible 中,如何将活动角色的变量组合到一个数组中?

    看着 在 Ansible 中 如何将不同文件中的变量合并到一个数组中 答案之一建议使用包含变量要将多个来源的变量放入一个数组中 这是almost我需要什么 但不完全是 我正在设置 cloudfront logging 它需要 a 中的项目a
  • Qt 使应用程序始终位于 Weston/Wayland 平台之上

    我想在 Wayland Weston 桌面系统中安排两个应用程序的焦点 两个应用是 用 Qt QML 编写 全屏 使用 Wayland 客户端 API OpenGL 编写 全屏 我想让 App 1 始终位于顶部 App 2 始终位于底部 即
  • 使用 ElementTree 从混合元素 xml 标签中获取文本

    我正在使用 ElementTree 来解析我拥有的 XML 文档 我从以下位置获取文本u标签 其中一些包含混合内容 我需要过滤掉或保留为文本 我有两个例子 u u
  • 删除 id=".xxx" 的 div 或 span

    我无法删除 id 带有句点或星号的 div div div div div 我有 jquery 代码 它删除了 div div 但不是上面的 不是在寻找 jQuery 代码 但它需要正斜杠吗 来自 anurag 的请求 JavaScript
  • 回调到可变的 self

    有没有一种方法 在 Rust 中 可以将可变的借用自我发送到回调而不需要mem replace我在以下 MWE 中使用的 hack 我正在使用 Rust stable 1 11 0 use std mem trait Actable fn
  • 如何在强制推送基础分支后更新我的功能分支。我们只使用rebase,禁止合并

    我们正在使用 git 中的一个非常简单的结构 首先我们有我们的master branch 下面我们有develop 最后我们可以有任何feature branch 我们仅使用 rebase 来更新分支上的历史记录 然后转发到上述分支 每周
  • 集合编辑器未针对 TPersistent 属性中的 TCollection 属性打开

    我有我的自定义集合属性 当它是我的组件的直接成员时 它工作得很好 但我想将集合属性移动到组件内的 TPersistent 属性 现在问题来了 它不起作用 双击对象检查器中的集合属性通常会打开集合编辑器 但现在不再这样了 首先 我应该将什么传