Delphi - метод GetText медленного дерева виртуальных строк при большом количестве узлов - PullRequest
3 голосов
/ 28 июля 2010

Я еще не очень разбираюсь в компоненте TVirtualStringTree, поэтому, возможно, я упустил что-то тривиальное.

Мое приложение собирает информацию о файле в запись (FileName, Path, Size) и отображает данные в виртуальном дереве строк.

Теперь, когда есть много узлов (200K +), я испытываю сильное замедление, все дерево в основном отстает. Мне известно, что объем памяти достаточно велик только для одних только данных записи, но я обнаружил, что задержка вызвана методом OnGetText VST. При этом не имеет значения, читает ли метод фактические данные или устанавливает для CellText статическую строку (например, CellText: = 'Test';) замедление является значительным. Если я выйду из OnGetText без настройки CellText, он будет работать нормально - даже если в моем дереве будет 1000000 узлов. Кроме того, если я сверну дерево (FullCollapse), скрывающее таким образом 90% моих узлов, OnGetText также будет работать нормально или, по крайней мере, намного лучше.

Насколько я понимаю, OnGetText вызывается только для реально видимых экранных узлов, поэтому я не понимаю, почему это такая проблема с большим количеством узлов в дереве.

У кого-нибудь есть намеки на то, чтобы я указывал мне направление?

EDIT:

Delphi Version: D2010 Версия VST: 4.8.6

Мой код в его простейшей тестовой форме в основном выглядит следующим образом:

var
  SkipGetText : boolean;

procedure TXForm.VSTGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
begin
  if SkipGetText then exit;
  CellText := 'TEST';
  // actual code commented out to reduce complications
end;

Если я установлю CellText, он запаздывает, если я выхожу, это не так. Как ни странно, чем дальше я прокручиваю, тем хуже.

Вот что назначено NodeData:

type
  PVSData = ^Fi;
  Fi = Packed Record
    Name, Dir, Ext: String;
    Size: Int64;
  end;

procedure TXForm.AddFile( const RootFolder:string; const SR: TSearchRec );
var
  FileInfo: PVSData;
  FileSize: Int64;
  Node: PVirtualNode;
begin
  Node          := VST.AddChild(nil);
  INC(AllFiles);
  FileInfo      := VST.GetNodeData(Node);
  FileInfo^.Name := SR.Name;
  FileInfo^.Dir  := RootFolder;

  Int64Rec(FileSize).Hi := SR.FindData.nFileSizeHigh;
  Int64Rec(FileSize).Lo := SR.FindData.nFileSizeLow;
  FileInfo^.Size         := FileSize;
end;

procedure TXForm.VSTPaintText(Sender: TBaseVirtualTree;
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
begin
  if SkipPaintText then exit;

  case ListView.GetNodeLevel(Node) of
    0: TargetCanvas.Font.Color := Color1;
    else TargetCanvas.Font.Color := Color2;
  end;
end;

procedure TXForm.VSTBeforeCellPaint(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
begin
  case ListView.GetNodeLevel(Node) of
    0: TargetCanvas.Font.Color := Color1;
    else TargetCanvas.Font.Color := Color2;
  end;
end;

Я заметил, что расширение / свертывание и повторное расширение каким-то образом улучшают ситуацию, но я не могу сказать, почему это может оказать какое-то влияние.

Ответы [ 4 ]

3 голосов
/ 29 июля 2010

Если какой-либо из ваших столбцов имеет авторазмер, тогда элемент управления должен знать ширину всех значений узлов, чтобы определить максимум.

1 голос
/ 14 августа 2010

Проблема решена. Оказывается, при удалении узлов могла возникнуть сложность. Вместо удаления всех дочерних узлов родительского узла был удален только родительский узел. Я ожидал, что дочерние узлы также будут удалены автоматически, но когда я изменил код, чтобы сначала удалить потомки, а затем родительский узел, отставание исчезло. Теперь я могу загрузить миллион имен файлов в дерево без задержки.

1 голос
/ 29 июля 2010

Странно, я думал, что это был весь дизайн VST, который загружал только узлы ячеек для узлов в активном представлении, а не все дерево. Вы уверены, что это не какой-то другой фактор в коде, который вы не показываете, например, существует ли файл для каждого узла или около того?

1 голос
/ 28 июля 2010

Вы не сказали, какую версию Delphi вы используете.В версиях, предшествующих D2009, TVirtualTreeView использует строковый тип WideString, который, как правило, медленный по своей сути, так как не имеет семантики подсчета ссылок и копирования при записи, которую имеет AnsiString, поэтому постарайтесь свести к минимумуСтроковые операции в максимально возможной степени.В D2009 и более поздних версиях TVirtualTreeView использует более новый UnicodeString строковый тип вместо WideString.

...