Произвольное рисование элементов TCustomListbox - PullRequest
0 голосов
/ 01 мая 2018

Я переписываю компонент VCL, показывая настроенный TCustomListbox для Firemonkey в Delphi 10.2. Настройка использовала переопределенный DrawItem, в основном добавляя некоторые отступы и устанавливая цвет текста в зависимости от текста элемента и индекса.

DrawItem сделал это довольно легко, но, похоже, ничего подобного в FMX нет. Я могу переопределить PaintChildren и нарисовать каждый элемент самостоятельно, но тогда он выглядит по-другому, и мне приходится иметь дело с прокруткой и всем остальным. Я только начинаю с FMX и пока не имею источников .

  • Есть ли замена DrawItem в FMX? Возможно, я пропустил это.

  • Если нет, то как получить необходимую информацию? По сути, прямоугольник для рисования и в идеале используемый стиль.

Проблемы

Решение Ханса работает, но имеет несколько серьезных проблем:

Цвет

Установка цвета не работает, текст всегда черный. Я пробовал различные возможности, включая эту:

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 мс на элемент.

1 Ответ

0 голосов
/ 07 мая 2018

Вот пример того, как это можно сделать. Ключ должен установить Parent (пользовательский) ListBoxItem в 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 во многих местах, потому что вы можете иметь ComboBoxes, EditBoxes и все другие элементы управления в ListboxItem. Это открывает очень динамичный (на основе списка) макет экрана, который легко адаптируется ко всем платформам и размерам экрана.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...