3

私はまだTVirtualStringTreeコンポーネントの経験があまりないので、些細なことを見落としているかもしれません。

私のアプリはファイル情報をレコード(FileName、Path、Size)に収集し、仮想文字列ツリーにデータを表示します。

ノードがたくさんある場合(200K以上)、大幅な速度低下が発生すると、ツリー全体が基本的に遅れます。レコードデータだけではメモリフットプリントが非常に大きいことは承知していますが、ラグはVSTのOnGetTextメソッドが原因であることがわかりました。これにより、メソッドが実際のデータを読み取るか、CellTextを静的文字列に設定するか(たとえば、CellText:='Test';)、速度の低下は重要です。CellTextを設定せずにOnGetTextを終了すると、ツリーに1,000,000個ものノードがある場合でも正常に機能します。また、ノードの90%をこのように非表示にしてツリーを折りたたむと(FullCollapse)、OnGetTextは正常に動作するか、少なくともはるかに優れた動作をします。

私が理解している限り、OnGetTextは実際に表示される画面上のノードに対してのみ呼び出されるため、ツリー内のノードが大量にある場合にこれがこのような問題になる理由はわかりません。

誰かが私をある方向に向けるためのヒントがありますか?

編集:

Delphiバージョン: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

4 に答える 4

3

列のいずれかが自動サイズ設定されている場合、最大値を決定するために、コントロールはすべてのノードの値の幅を知る必要があります。

于 2010-07-28T20:01:45.410 に答える
1

使用しているDelphiのバージョンはわかりませんでした。D2009より前のバージョンでTVirtualTreeViewは、文字列型を使用しWideStringます。これは、参照カウント、コピーオンライトのセマンティクスがないため、一般に本質的に低速ですAnsiString。したがって、文字列操作を可能な限り最小限に抑えるようにしてください。D2009以降でTVirtualTreeViewは、の代わりに新しいUnicodeString文字列タイプを使用しWideStringます。

于 2010-07-28T19:34:39.663 に答える
1

奇妙なことに、ツリー全体ではなく、アクティブビューのノードのセルノードのみをロードするのはVSTの全体的な設計だと思いました。すべてのノードに対してfileexistsを実行するなど、コードに表示されていない他の要素がないことを確認しますか?

于 2010-07-29T03:37:07.643 に答える
1

問題が解決しました。結局のところ、ノードの削除中に問題が発生した可能性があります。親ノードのすべての子を削除する代わりに、親ノードのみが削除されました。子ノードも自動的に削除されることを期待していましたが、最初に子を削除し、次に親ノードを削除するようにコードを変更すると、遅延はなくなりました。これで、100万個のファイル名をラグなしでツリーにロードできます。

于 2010-08-14T07:58:23.937 に答える