Медленное обновление содержимого TTreeView (SOLVED)

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Ответить
RRYTY
постоялец
Сообщения: 257
Зарегистрирован: 25.12.2021 09:00:32

Медленное обновление содержимого TTreeView (SOLVED)

Сообщение RRYTY »

Речь идет о компоненте TTreeView в Lazarus v.2.0.12 и позднее ТОЛЬКО под управлением ОС Linux.

Ситуация: имеется копонент TTreeView, в котором программно создается около 1E+5 TTreeNode. Несколько тысяч корневых, остальные - дочерние, первого уровня. Естественно, создание занимает ощутимое время. Экспериментально было выяснено, что если скрыть компонент TTreeView на все время заполнения данными (visible=false), то процесс заметно (в несколько раз) ускоряется. Очевидно, это связано с отрисовкой компонента при добавлении нодов.

С версиями Lazarus 1.x.x все было приемлемо. Но в версиях 2.x.x визуальное скрытие компонента в ОС Linux перестало давать требуемый эффект. Решением был признан более кардинальный способ исключения обработки событий отрисовки. Сам компонент TTreeView отвязывается от родителя (Parent=nil), заполняется данными, затем снова привязывается к родителю.

Вопрос: может есть какой-то более гуманный способ быстро загрузить в TTreeView относительно большое количество данных?
Последний раз редактировалось RRYTY 09.01.2024 21:40:11, всего редактировалось 2 раза.
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3067
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

RRYTY Рассматривали ли вы Virtual TreeView?
iskander
энтузиаст
Сообщения: 630
Зарегистрирован: 08.01.2012 18:43:34

Сообщение iskander »

А если так попробовать?

Код: Выделить всё

...
  TreeView1.BeginUpdate;
  try
    //добавляем ноды
  finally
    TreeView1.EndUpdate;
  end;
...
RRYTY
постоялец
Сообщения: 257
Зарегистрирован: 25.12.2021 09:00:32

Сообщение RRYTY »

Снег Север » 25.12.2021 12:39:50

RRYTY Рассматривали ли вы Virtual TreeView?


Не рассматривл, не знаю что это. Поподробнее, пожалуйста.

iskander » 25.12.2021 12:43:53

А если так попробовать?


Поясните, пожалуйста. Непонятно, что имеется ввиду.

Добавлено спустя 9 минут 51 секунду:
Снег Север, Virtual TreeView - это https://www.jam-software.com/virtual-treeview ?
iskander
энтузиаст
Сообщения: 630
Зарегистрирован: 08.01.2012 18:43:34

Сообщение iskander »

RRYTY писал(а):Непонятно, что имеется ввиду.

Так нет никакого подтекста, просто сравните время выполнения этого

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
var
  Node, Node1, Node2, Node3: TTreeNode;
  I, J, K, M: Integer;
begin
  TreeView1.AutoExpand := True;
  Node := TreeView1.Items.Add(nil, 'Root');
  for I := 1 to 10 do
    begin
      Node1 := TreeView1.Items.AddChild(Node, IntToStr(I));
      for J := 1 to 10 do
        begin
          Node2 :=  TreeView1.Items.AddChild(Node1, IntToStr(J));
          for K := 1 to 10 do
            begin
              Node3 :=  TreeView1.Items.AddChild(Node2, IntToStr(K));
              for M := 1 to 10 do
                TreeView1.Items.AddChild(Node3, IntToStr(M));
            end;
        end;
    end;
end;

и вот этого

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
var
  Node, Node1, Node2, Node3: TTreeNode;
  I, J, K, M: Integer;
begin
  TreeView1.AutoExpand := True;
  TreeView1.BeginUpdate;
  try
    Node := TreeView1.Items.Add(nil, 'Root');
    for I := 1 to 10 do
      begin
        Node1 := TreeView1.Items.AddChild(Node, IntToStr(I));
        for J := 1 to 10 do
          begin
            Node2 :=  TreeView1.Items.AddChild(Node1, IntToStr(J));
            for K := 1 to 10 do
              begin
                Node3 :=  TreeView1.Items.AddChild(Node2, IntToStr(K));
                for M := 1 to 10 do
                  TreeView1.Items.AddChild(Node3, IntToStr(M));
              end;
          end;
      end;
  finally
    TreeView1.EndUpdate;
  end;
end;
RRYTY
постоялец
Сообщения: 257
Зарегистрирован: 25.12.2021 09:00:32

Сообщение RRYTY »

iskander, теперь понятно. Сейчас попробую.

Добавлено спустя 10 минут 26 секунд:
Работает отлично! Спасибо.
Alex2013
долгожитель
Сообщения: 3212
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

RRYTY писал(а):Речь идет о компоненте TTreeView в Lazarus v.2.0.12 и позднее ТОЛЬКО под управлением ОС Linux.

Вопрос: может есть какой-то более гуманный способ быстро загрузить в TTreeView относительно большое количество данных?


1 Parent=nil вполне "гуманная" операция. Я обычно в подобных случаях вообще создаю TTreeView заполняю данными и только потом вставляю в форму.
2 Возможно стоит копнуть внутренности TTreeView и создавать нужную структуру данных отдельно от TTreeView?
3 Строго говоря TTreeView вообще не предназначен для работы с большими массивами данных.
Зы
Впрочем TreeView1.BeginUpdate; и TreeView1.EndUpdate; действительно могут помочь . :idea:
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3067
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

VirtualTreeview is a TTreeView control built from ground up.

Its main characteristics are :
it is extremely fast. Adding one million nodes takes only ~700 milliseconds
very small memory foot print. by only allocating about 60 bytes per node
optimized for high speed access. It takes as few as 0.5 seconds to traverse one million nodes
RRYTY
постоялец
Сообщения: 257
Зарегистрирован: 25.12.2021 09:00:32

Сообщение RRYTY »

Alex2013 BeginUpdate/EndUpdate, судя по всему для этого и созданы, вот только описание у них совершенно неявное и в примерах обычно не встречается. Кто ж примеры делает на сотни тысяч нодов...
TTreeView рассчитан на совесть разработчика. Понятно же, что это в первую очередь визуальный компонент, а не движок БД. :) Но в моем случае он прекрасно подходит. Все данные жестко структурированы и ограничены по объему.

Снег Север Спасибо за наводку. Пригодится.
Ответить