delphi - TCustomListbox 项目的自定义绘图

标签 delphi firemonkey vcl delphi-10.2-tokyo

我正在重写一个 VCL 组件,在 Delphi 10.2 中向 Firemonkey 显示自定义的 TCustomListbox。自定义使用了重写的 DrawItem,基本上添加了一些缩进并根据项目文本和索引设置文本颜色。

DrawItem 使它变得相当简单,但 FMX 中似乎没有这样的东西。我可以重写 PaintChildren 并自己绘制每个项目,但它看起来会有所不同,我必须自己处理滚动和所有事情。我刚刚开始使用 FMX 和 don't have the sources yet .

  • FMX 中有 DrawItem 替代品吗?我可能错过了。

  • 如果没有,它如何获取所需的信息?基本上,是要绘制的矩形以及理想情况下使用的样式。

问题

汉斯的解决方案有效,但存在一些主要问题:

颜色

设置颜色不起作用,文本始终是黑色。我尝试了各种可能性,包括这个:

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 毫秒。

最佳答案

以下是如何完成此操作的示例。关键是将(自定义)ListBoxItemParent 设置为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 中拥有 ComboBox、EditBox 和所有其他控件。这将打开一个非常动态(基于列表)的屏幕布局,可以轻松适应所有平台和屏幕尺寸。

关于delphi - TCustomListbox 项目的自定义绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50118359/

相关文章:

通过连接到 SQLite 数据库使用应用程序网络共享的 Delphi 登录表单

delphi - Firemonkey半透明Image3D有时不透明

delphi - 位图裁剪 : some misunderstandings and some help would be welcome

delphi组件属性: TObjectList<TPicture>

delphi - 任务栏上显示多个实例的 SDI 应用程序

delphi - Delphi中将数据发送到USB打印机

arrays - 如何检查数组中是否存在字符串?

sql-server - 使用 VCL for the web (intraweb) 作为将 Web 界面添加到传统非分层(2 层)Delphi win32 应用程序的技巧是否有意义?

delphi - Delphi 中嵌套 for 循环的替代方案

delphi - TStream 作为 StringList 内的对象