私はまだ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;
どういうわけか拡張/折りたたみと再拡張が状況を改善するように見えることに気づきましたが、これが実際に何らかの影響を与える可能性がある理由を説明することは私を超えています。