В процессе разработки пользовательских приложений, работающих с большими объемами данных, часто возникает необходимость эффективного отображения этих данных в интерфейсе. В Delphi XE7, как и в других версиях, компонент TListView является одним из наиболее популярных для отображения списков и табличных данных. Однако, при попытке заполнить TListView большим количеством элементов (например, 10,000 или 25,000), можно столкнуться с низкой производительностью. В этой статье мы рассмотрим возможные методы ускорения заполнения TListView, а также обсудим некоторые аспекты работы с этим компонентом.
Проблема: низкая производительность при заполнении TListView
Пользователь JohnLM столкнулся с проблемой замедления при попытке заполнить TListView большим количеством элементов. Даже при использовании методов BeginUpdate и EndUpdate, время заполнения списка оставалось значительным: для 10,000 элементов — около 1.6 секунд, а для 25,000 элементов — около 7.6 секунд. Исследования показали, что основная проблема заключается в том, что TListView по умолчанию работает в режиме "не виртуального" (non-virtual mode), что приводит к значительным затратам времени на отрисовку каждого элемента.
Решение: использование виртуального режима (Virtual Mode)
Для ускорения работы с большими объемами данных рекомендуется использовать виртуальный режим (virtual mode) для компонента TListView. В этом режиме данные хранятся в памяти, а отображение элементов происходит по мере необходимости. Это значительно уменьшает нагрузку на процессор и ускоряет процесс заполнения списка.
Как использовать виртуальный режим
Для использования виртуального режима необходимо выполнить следующие шаги:
Установите свойство OwnerData компонента TListView в True.
Назначьте обработчик события OnData для отображения данных для каждого элемента.
Установите свойство Items.Count для определения общего числа элементов в списке.
Пример кода для инициализации виртуального режима и заполнения списка:
type
TItemData = record
LN: Integer;
ItemNo: string;
Desc: string;
end;
private
lvItems: array of TItemData;
procedure TForm1.btnAddClick(Sender: TObject);
var
Col : TListColumn;
SW : TStopwatch;
s : string;
i : Integer;
begin
Col := lv1.Columns.Add;
Col.Caption := 'LN';
Col.Alignment := taLeftJustify;
Col.Width := 30;
Col := lv1.Columns.Add;
Col.Caption := 'ItemNo';
Col.Alignment := taLeftJustify;
Col.Width := 60;
Col := lv1.Columns.Add;
Col.Caption := 'Desc';
Col.Alignment := taLeftJustify;
Col.Width := 160;
SetLength(lvItems, 25000);
SetLength(ary,10); // create the array length (1,2,3,4,5,6,7,8,9,0) chars
beep;
SW := TStopWatch.StartNew; // start timing it
for i := Low(lvItems) to High(lvItems) do begin
ary := genRandValues; // generate random numbers ie (2,9,8,4,7,5,6,0,1,3)
s := ListToStr(ary); // convert array list into a string var ie ('2984756013')
lvItems[i].LN := i;
lvItems[i].ItemNo := s;
lvItems[i].Desc := s;
end;
lv1.Items.Count := Length(lvItems);
SW.Stop; // finish timing
eb1.Text := IntToStr(SW.ElapsedTicks) + ' ticks / ' + IntToStr(SW.ElapsedMilliseconds) + ' ms';
beep;
end;
procedure TForm1.lv1Data(Sender: TObject; Item: TListItem);
begin
Item.Caption := lvItems[Item.Index].LN.ToString(); // add the major field, ie 'LN', thus the populate with the index as line numbers
Item.SubItems.Add(lvItems[Item.Index].ItemNo); // itemno ie '2984756013', and so on.
Item.SubItems.Add(lvItems[Item.Index].Desc); // desc ie same, ...
end;
Преимущества виртуального режима
Быстрое заполнение списка: Виртуальный режим значительно ускоряет процесс заполнения списка, особенно при работе с большими объемами данных.
Экономия ресурсов: Виртуальный режим минимизирует использование памяти и процессорных ресурсов, так как данные хранятся в памяти, а отображение происходит по мере необходимости.
Улучшенная производительность: Виртуальный режим позволяет улучшить общую производительность приложения, особенно при работе с большими объемами данных.
Дополнительные оптимизации
Кроме использования виртуального режима, можно применить несколько дополнительных оптимизаций для улучшения производительности TListView:
Использование BeginUpdate и EndUpdate: Как уже было упомянуто, использование методов BeginUpdate и EndUpdate позволяет предотвратить избыточные перерисовки и ускоряет процесс добавления, удаления или вставки элементов.
lv1.Items.BeginUpdate;
try // add multiple items
finally
lv1.Items.EndUpdate;
end;
Отключение событий изменения: Если у вас есть обработчики событий изменения (например, OnChange), рекомендуется временно отключить их во время заполнения списка, чтобы предотвратить вызовы этих обработчиков для каждого добавленного элемента.
Использование двойного буферинг: В некоторых случаях использование двойного буферинга (DoubleBuffered := True) может улучшить отображение списка, особенно при работе с большими объемами данных или при наличии артефактов отрисовки.
lv1.DoubleBuffered := True;
Заключение
Использование виртуального режима (virtual mode) является наиболее эффективным способом ускорения заполнения TListView в Delphi XE7, особенно при работе с большими объемами данных. Дополнительные оптимизации, такие как использование BeginUpdate и EndUpdate, отключение событий изменения и использование двойного буферинга, могут значительно улучшить производительность и стабильность приложения. Следуя этим рекомендациям, вы сможете создать быстрые и эффективные приложения, даже при работе с большими объемами данных.
В статье рассматривается, как ускорить заполнение компонента TListView в Delphi XE7 при работе с большими объемами данных, предлагая использовать виртуальный режим и дополнительные оптимизации для повышения производительности.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.