Delphi FireMonkey动态创建ListView项内按钮报错求助
问题根源
- 控件内存管理错误:创建
TListItemTextButton时使用nil作为Owner,导致控件的内存释放不归ListViewItem管理,窗体关闭或ListViewItem被回收时会触发无效指针操作。 - 更新流程错误:在
AItem.EndUpdate之后才将按钮加入Objects集合,破坏了ListViewItem的原子更新逻辑,引发点击时的访问违例。 - 冗余代码:重复设置
PlaceOffset.X,且未设置PlaceOffset.Y可能导致按钮位置异常。
修正方案
- 创建按钮时将Owner设为对应的
AItem,让ListViewItem负责控件的生命周期管理。 - 在
BeginUpdate和EndUpdate的原子操作块内完成按钮属性设置与对象添加,保证ListViewItem状态一致。 - 修正位置偏移的冗余设置,补充垂直方向偏移。
- 用
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
相关产品推荐
相关产品推荐

