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

如何在加载数据时阻止FMX TMemo更新?BeginUpdate无效怎么办

问题原因

当TMemo.ControlType设置为TControlType.Platform时,组件底层调用当前操作系统的原生编辑框控件,TMemo.Lines.BeginUpdate/EndUpdate仅作用于FMX框架内部的字符串列表缓存,不会通知原生控件暂停渲染,因此每次调用Add时原生控件都会触发重绘,就会出现实时刷新的现象。同时循环单次调用Lines.Add本身也会产生额外性能开销,进一步放大了该问题。

解决方案

方案1:批量赋值内容(兼容所有ControlType,性能最优)

不要循环调用Add,先把所有行写入临时容器,最后一次性赋值给Memo,避免单次添加触发的多次重绘:

procedure TForm2.Memo1DblClick(Sender: TObject);
var
  i: Integer;
  sb: TStringBuilder;
const
  Line = '1234567890_1234567890_1234567890_1234567890_1234567890_1234567890';
begin
  Memo1.ControlType := TControlType.Platform;
  sb := TStringBuilder.Create;
  try
    for i := 1 to 1000 do
      sb.AppendLine(Line);
    Memo1.Text := sb.ToString;
  finally
    sb.Free;
  end;
end;

也可以用TStringList替代TStringBuilder,最后调用Memo1.Lines.Assign(临时列表)实现同样效果。


方案2:使用FMX自绘模式

如果不需要依赖原生控件的特殊特性,把ControlType改为TControlType.Styled,此时Lines.BeginUpdate/EndUpdate就能正常生效,暂停渲染直到所有内容添加完成:

procedure TForm2.Memo1DblClick(Sender: TObject);
var
  i: Integer;
const
  Line = '1234567890_1234567890_1234567890_1234567890_1234567890_1234567890';
begin
  Memo1.Lines.Clear;
  Memo1.ControlType := TControlType.Styled;
  Memo1.Lines.BeginUpdate;
  try
    for i := 1 to 1000 do
      Memo1.Lines.Add(Line);
  finally
    Memo1.Lines.EndUpdate;
  end;
end;

方案3:临时暂停控件渲染

如果必须使用原生控件模式,可以调用FMX控件的SuspendRendering方法手动冻结渲染,内容加载完成后再恢复:

procedure TForm2.Memo1DblClick(Sender: TObject);
var
  i: Integer;
const
  Line = '1234567890_1234567890_1234567890_1234567890_1234567890_1234567890';
begin
  Memo1.Lines.Clear;
  Memo1.ControlType := TControlType.Platform;
  Memo1.SuspendRendering;
  try
    for i := 1 to 1000 do
      Memo1.Lines.Add(Line);
  finally
    Memo1.ResumeRendering;
  end;
end;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 01:27:03