2014-02-08 41 views
0

TreeView項目和數據包含文件名,數據包含TBitmap。我的問題涉及以某種方式將項目和數據保存在樹視圖中,以便項目和數據可以在線程中訪問。如果可以,保存項目和數據後,我可以訪問線程中的項目和數據,而不是在Synchronize中訪問它。由於現在編寫的代碼太慢,因爲訪問GUI TreeItems和Data in Synchronize。有沒有辦法保存Treeview的項目和數據,以便可以在線程中訪問它?

if not Terminated then 
begin 
    Synchronize(
    procedure 
    var 
    i: integer; 
    begin 
    for i := 1 to Form1.TreeView1.Items.Count - 1 do 
    begin 
     { get the bitmap } 
     iImageEnIO.WIAParams.ProcessingBitmap := iImageEnIO.IEBitmap; 
     { The following line prevents me from accessing the TreeView data in a thread } 
     iImageEnIO.WIAParams.Transfer(TIEWiaItem(Form1.TreeView1.Items[i].Data), False); 
     { Set the filename } 
     iFilename := Form1.TreeView1.Items[i].Text + '.jpg'; 
     { Add the image to the iIEImageList } 
     iIndex := iIEImageList.AppendImageRef(TIEBitmap.Create(iImageEnIO.IEBitmap), iFileName); 
     iIEImageList.Filename[iIndex] := iFileName; 
    end; 
end); 

的線程代碼訪問的位圖線程本身工作得非常好,但如果我可以移動獲取位圖到線程的代碼,而不是在同步會好得多。所以我的問題是「有沒有辦法在Synchronize中保存樹視圖項和數據,以便可以在Synchronize之外的線程中訪問」?

iImageEnIO.OnProgress := ImageEnProcProgress; 
    iImageEnIO.OnFinishWork := ImageEnProcFinishWork; 

    { Get the bitmap from the imagelist and save the image in the thread } 
    iCount := iIEImageList.ImageCount; 
    for j := 0 to iCount-1 do 
     begin 
     { get the filename from the string list } 
     iFilename := iIEImageList.Filename[j]; 
     { attach the iIEBitmap2 to iImageEnIO } 
     iImageEnIO.AttachedIEBitmap := iIEImageList.Image[j]; 
     iPath := IncludeTrailingPathDelimiter(iFolder) + iFilename; 
     iImageEnIO.SaveToFile(iPath); 
     end; 

我希望我已經正確地問了我的問題,並且很清楚我想要做什麼。

+0

如果我正確理解你的問題,我不需要保存後訪問位圖。我只需要能夠訪問節點項目以獲取文件名並將該位圖添加到iIEImageList,然後再將該文件保存到線程中的磁盤。 – Bill

回答

3

我想把它的頭。你想知道如何在執行線程方法時從GUI控件讀取數據。這是一個基本的設計缺陷。解決您的問題將涉及不嘗試這樣做。

樹視圖不應該是數據的所有者。它是一個GUI控件,應該僅僅提供一個數據視圖。數據應該保存在一個不受VCL線程規則約束的結構中。一旦將數據結構從GUI中分離出來,您的問題就變得微不足道了。一旦你達到這一點,就沒有問題要解決。

那麼,你需要什麼樣的結構?儘管它存儲在樹形視圖中,但它似乎是一個扁平列表。將其存儲在TList<T>容器中。你使用什麼T?那麼,這只是每個項目所需的信息。這可能是一個記錄。或者它可能是一個班級。如果您在項目類型中保存了非值類型的對象,那麼類可能會更好。在這種情況下,TObjectList<T>更合適。因此,它應該是這樣的:

type 
    TItem = class 
    private 
    FFileName: string; 
    FBitmap: TBitmap; 
    end; 

那麼你的容器簡直是TObjectList<TItem>。實例這樣的:

FItems := TObjectList<TItem>.Create(True); 

True對於OwnsObjects參數。這意味着當您從容器中刪除項目或刪除容器時,項目被銷燬。

此時,您可以通過迭代容器來填充樹視圖,並創建表示項目的節點。

然後當你的線程需要對數據進行操作時,它可以參考FItems,它與GUI控件分開。

故事的寓意是,您不應該使用GUI控件作爲主要數據容器。

+0

是否將FItems定義爲TItem? – Bill

+0

不需要看它是如何實例化的。它是'TObjectList ' –

+0

使用連接符; TItem = class(TObjectList) private FFileName:string; FIEBitmap:TIEBitmap; 結束; – Bill

相關問題