2010-07-28 37 views
3

我還沒有非常豐富的TVirtualStringTree組件經驗,因此也許我忽略了一些微不足道的東西。德爾福 - 虛擬字符串樹緩慢GetText方法在大量的節點

我的應用程序將文件信息收集到記錄(文件名,路徑,大小)並顯示在虛擬字符串樹中的數據。

現在,當有很多節點(200K +)時,我經歷了一個沉重的減速,整個樹基本上滯後。我知道內存佔用量非常大,只有記錄數據,但我發現滯後是由VST的OnGetText方法引起的。 因此,如果方法讀取實際數據或將CellText設置爲靜態字符串(例如,CellText:='Test';),則減速效果顯着無關緊要。 如果我在不設置CellText的情況下退出OnGetText,它可以正常工作 - 即使在我的樹中也有多達1,000,000個節點。 另外,如果我摺疊Tree(FullCollapse)隱藏這種方式90%的節點,OnGetText表現還可以,或者至少好得多。

據我所知,OnGetText僅僅被稱爲實際可見的屏幕節點,因此我不明白爲什麼這是樹中有大量節點的問題。

有人有任何提示讓我指出我的方向?

編輯:

德爾福版本: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; 

我注意到,那展開/摺疊和再膨脹在某種程度上似乎改善這種情況,但它超出了我知道爲什麼這樣做可能會造成任何影響。

+0

如果您顯示您的代碼,至少您在OnGetText處理程序中擁有的代碼,您將得到更好的答案。順便說一句,我只有經歷了緩慢的起伏,當我在一個方法中做了一些「愚蠢的事情」時,幾乎每個鼠標移動都會被調用... – 2010-07-28 17:09:58

+0

Hi BlackOut!歡迎來到StackOverflow。這是一個很好的第一個問題。我對VirtualStringTree瞭解不多,因此我不會嘗試發佈真正的答案,但聽起來您的性能隨着開放節點數量的增加呈線性下降。這使得看起來像設置CellText必須掃描樹的所有節點出於某種原因。嘗試查看代碼並查看在更改CellText時是否可以找到某種線性搜索。 – 2010-07-28 17:14:41

+0

我的代碼非常基本,因爲我已經刪除了每個可能使事情複雜化以便進行調試的部分。 與此同時,我想我可能會看到一些東西,因爲它似乎一旦我再次崩潰並展開樹,它就可以正常工作。我會給它更多的測試和明天更新我的文章,或者如果我碰巧找出什麼是負責任的,請添加一個答案。 – BlackOut 2010-07-28 23:54:07

回答

1

問題解決。事實證明,刪除節點時可能會出現複雜情況。不是刪除父節點的所有子節點,只有父節點已被刪除。我預計子節點也會自動刪除,但是當我更改代碼以首先刪除子節點時,父節點的滯後消失了。現在我可以無延遲地將一百萬個文件名加載到樹中。

1

你沒有說你正在使用哪個版本的Delphi。在D2009之前的版本中,TVirtualTreeView使用WideString字符串類型,這種字符串類型通常本質上很慢,因爲它沒有AnsiString具有的引用計數,寫時複製語義,因此儘量儘量減少字符串操作。在D2009及更高版本中,TVirtualTreeView使用較新的UnicodeString字符串類型而不是WideString

+0

是的,我應該提供該信息。 我使用Delphi 2010與虛擬字符串樹版本4.8.6 – BlackOut 2010-07-28 23:48:00

3

如果您的任何列都是自動調整大小的,那麼控件需要知道所有節點值的寬度以確定最大值。

1

奇怪的是,我認爲這是VST的整個設計,只爲活動視圖中的節點加載cellnodes,而不是整個樹。你確定它不是代碼中的其他因素,你沒有顯示,比如爲每個節點做一個文件存在的東西嗎?