我正在重写一个VCL组件,在Delphi 10.2中向Firemonkey显示一个自定义的TCustomListBox.自定义使用重写的DrawItem,基本上添加一些缩进并根据项目文本和索引设置文本颜色.
DrawItem让它变得相当容易,但在FMX中似乎没有这样的东西.我可以覆盖PaintChildren并自己绘制每个项目,但它看起来不同,我必须自己处理滚动和一切.我刚开始使用FMX和don’t have the sources yet.
> FMX中是否有DrawItem替换?我可能错过了它.
>如果没有,它如何获得所需信息?基本上,要绘制的矩形和理想的使用样式.
问题
Hans的解决方案有效,但有一些重大问题:
颜色
设置颜色不起作用,文本始终为黑色.我尝试了各种可能性,包括这个:
PROCEDURE TMyItem.Paint; BEGIN TextSettings.FontColor := TAlphaColorRec.Red; INHERITED; END;
速度
打开一个包含180个项目的框可能需要两秒钟.我们需要许多项目和它们的数量实际上是我们需要一个自定义框的原因(我们使用我们组件的TEdit部分提供过滤).使用没有TMyItem的字符串的版本更快(虽然可能比VCL版本慢),但是使用这些项目似乎更慢了(它比填充类似的HTML列表慢).
或者是其他东西?没有来源,几乎没有文件,我无法分辨.
我试图缓存项目以供重用,但这没有帮助.
看起来使用自定义项实际上比使用字符串更快(以毫秒为单位):
nItems String TMyItem 200 672 12 2000 5604 267 20000 97322 18700
当内容多次更改时,速度问题似乎会累积.我当时正在使用FListBox.Items.Clear;然后我试过了
n := FListBox.Items.Count; FOR i := 0 TO n-1 DO FListBox.ListItems[n-1-i].Free;
最后是FListBox.Clear;,这是最有意义的(我最后发现).最后,每件物品似乎需要2毫秒.
解决方法
这是一个如何完成它的例子.关键是将(自定义)ListBoxItem的Parent设置为ListBox.这会将其附加到其项目列表中.我在构造函数中设置了父级,所以每次向列表框添加内容时都不必这样做(并记住它).
type tMyListBoxItem = class(TListBoxItem) strict private fTextLabel: TLabel; public constructor Create(aOwner: TComponent); property TextLabel: TLabel read fTextLabel; end; implementation constructor tMyListBoxItem.Create(aOwner: TComponent); begin inherited; fTextLabel := TLabel.Create(self); fTextLabel.Parent := self; Assert(aOwner is TFMXObject,'tMyListBoxItem.Create'); Parent := TFMXObject(aOwner); end; procedure tMyForm.FillListBox(aListBox: TListBox; aStringList: TStringList); var lItem: tMyListBoxItem; i: integer; begin aListBox.BeginUpdate; //to avoid repainting for every item added aListBox.Clear; for i := 0 to aStringList.Count-1 do begin lItem := tMyListBoxItem.Create(aListBox); lItem.TextLabel.Text := aStringList[i]; lItem.Margins.Left := 20; end; aListBox.EndUpdate; end;
我现在在许多地方使用自定义ListBoxItems,因为你可以在ListBoxItem中拥有ComboBoxes,EditBoxes和所有其他控件.这将打开一个非常动态(基于列表)的屏幕布局,可轻松适应所有平台和屏幕尺寸.