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

Delphi FireMonkey动态创建ListView项内按钮报错求助

Delphi FireMonkey ListView动态创建TListItemTextButton的错误解决

问题根源

  1. 控件内存管理错误:创建TListItemTextButton时使用nil作为Owner,导致控件的内存释放不归ListViewItem管理,窗体关闭或ListViewItem被回收时会触发无效指针操作。
  2. 更新流程错误:在AItem.EndUpdate之后才将按钮加入Objects集合,破坏了ListViewItem的原子更新逻辑,引发点击时的访问违例。
  3. 冗余代码:重复设置PlaceOffset.X,且未设置PlaceOffset.Y可能导致按钮位置异常。

修正方案

  1. 创建按钮时将Owner设为对应的AItem,让ListViewItem负责控件的生命周期管理。
  2. 在BeginUpdate和EndUpdate的原子操作块内完成按钮属性设置与对象添加,保证ListViewItem状态一致。
  3. 修正位置偏移的冗余设置,补充垂直方向偏移。
  4. 用try-finally包裹更新操作,避免异常导致ListViewItem处于更新锁定状态。

修正后的完整代码

procedure TForm1.btAddClick(Sender: TObject);
var
  AItem: TListViewItem;
begin
  AItem := ListView1.Items.AddItem;
end;

procedure TForm1.ListView1UpdateObjects(const Sender: TObject; const AItem: TListViewItem);
begin
  if AItem.Objects.FindObject('MyButtonCustom') = nil then
  begin
    Create_BT(AItem);
  end;
end;

procedure TForm1.Create_BT(const AItem: TListViewItem);
var
  LItem: TListItemTextButton;
begin
  // 将Owner设置为AItem,由ListViewItem管理控件内存
  LItem := TListItemTextButton.Create(AItem);
  AItem.BeginUpdate;
  try
    LItem.Name := 'MyButtonCustom';
    LItem.Text := 'MyButtonCustom';

    LItem.Height := 20;
    LItem.Width := 200;
    LItem.PlaceOffset.X := 0;
    LItem.PlaceOffset.Y := 0; // 补充垂直方向偏移,确保位置正确

    LItem.Align := TListItemAlign.Center;
    LItem.VertAlign := TListItemAlign.Center;

    LItem.TextAlign := TTextAlign.Center;
    LItem.TextVertAlign := TTextAlign.Center;

    // 在更新块内添加对象,保证ListViewItem状态一致
    AItem.Objects.Add(LItem);

    // 可选:添加按钮点击事件处理(示例)
    LItem.OnClick := procedure(Sender: TObject)
    begin
      ShowMessage('自定义按钮被点击');
    end;
  finally
    AItem.EndUpdate;
  end;
end;

额外注意事项

如果按钮点击事件中需要访问窗体或其他对象,需确保这些对象在事件触发时仍处于存活状态,避免因对象已释放引发新的访问违例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:13:16