如何在加载数据时阻止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
相关产品推荐
相关产品推荐

