如何解决向TListView加入大量数据产生的速度问题 |
尚未結案
|
LargeWon
一般會員 發表:3 回覆:10 積分:2 註冊:2002-12-24 發送簡訊給我 |
问题产生:我向TListView中加入5000 条数据需要12秒多,用户肯定不满意。
问题详述:
procedure TfrmMD.FillListView; var I, CurIndex: Integer; ARecord: TMasterDetailRecordBase; begin lvDetail.Items.BeginUpdate; try CurIndex := 0; lvDetail.Clear; for I := 0 to FMasterDetailMan.RecordCount - 1 do begin//这里FMasterDetailMan.RecordCount为5000 ARecord := TMasterDetailRecordBase(FMasterDetailMan.Records[I]); ARecord.AddToListView(lvDetail);//从这里调用TMasterDetailRecordBase.AddToListView方法,lvDetail为TListView对象 end; finally lvDetail.Items.EndUpdate; end; end; procedure TMasterDetailRecordBase.AddToListView(ListView: TListView); begin with ListView.Items.Add do begin Data := Self; Caption := FACaption; SubItems.Add(ParentID);//最耗时代码,使用SubItems.BeginUpdate/EndUpdate也不能解决 SubItems.Add(ID);//最耗时代码 end; end;调用TfrmMD.FillListView方法需要耗时12秒多,经过测试,发现以上代码最消耗时间的是给ListView.Items.Add.SubItems添加条目的代码(以上标注的两行,但这两行代码是必须的)。于是提出以下解决方案:向ListView中分组加入数据,例如每次加500条,当用户翻动ListView的时候若到达ListView显示数据的最后位置时再向其中加入500条数据,这就需要检测ListView当前显示数据条目的位置,从而须跟踪滚动条ScroolBar的消息,但ListView并无引出滚动条的滚动消息,所以这个方法看起来有一定难度,所以求助各位大大!如果还有其它方法可以解决本速度问题,也请不吝赐教。 發表人 - LargeWon 於 2004/05/11 15:12:20
------
老王 |
mustapha.wang
資深會員 發表:89 回覆:409 積分:274 註冊:2002-03-13 發送簡訊給我 |
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
LargeWon 你好
請改成如下試試,直接增加ListView的Items不要透過呼叫物件的方法,因為物件的弔用及方法的呼叫都會增加時間的,尤其在大量的迴圈內。 procedure TfrmMD.FillListView; var I, CurIndex: Integer; ARecord: TMasterDetailRecordBase; begin lvDetail.Items.BeginUpdate; try CurIndex := 0; lvDetail.Clear; for I := 0 to FMasterDetailMan.RecordCount - 1 do begin//这里FMasterDetailMan.RecordCount为5000 ARecord := TMasterDetailRecordBase(FMasterDetailMan.Records[I]); with lvDetail.Items.Add do begin Data := Self; Caption := FACaption; SubItems.Add(ParentID SubItems.Add(ID);//最耗时代码 end; // ARecord.AddToListView(lvDetail);//从这里调用TMasterDetailRecordBase.AddToListView方法,lvDetail为TListView对象 end; finally lvDetail.Items.EndUpdate; end; end; ...... |
TATSU
版主 發表:50 回覆:135 積分:62 註冊:2003-01-16 發送簡訊給我 |
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=47568 我曾經回答過有關問題,你可以參考一下 相關的設定:
ListView.OwnerData := True ; //不設定 Item
ListView.Items.Count := xx //設定數量
ListView.OnData event //ListView 提取資料 離線閱讀程式
|
LargeWon
一般會員 發表:3 回覆:10 積分:2 註冊:2002-12-24 發送簡訊給我 |
Chance36 的方法不可取,理由是数据的填充本是变化的,所以不能放到View里面。 TATSU 所言是一种解决方法,但由此法引出的问题也大伤脑筋:
1、ListView各列的排序:
本来列排序只同ListView相关,但现在必须自己对TList排序,且当TList的内容变化的时候必须添加新代码实现某列排序;也就是说,排序的操作由TListView端转移到了TList端,TListView是用户操作界面,TList是数据端,这样就破坏了MVC的处理原则,即对用户的操作处理应该放到View而不是数据处理端;
2、不能由代码指定某行为选中状态,使排序的时候不能固定原来选中的行:
lvDetail.Selected := lvDetail.Items[I]; lvDetail.ItemFocused := lvDetail.Items[I] //以上代码执行时均无效。望各位同行继续讨论。 發表人 - LargeWon 於 2004/05/12 14:09:34 發表人 - LargeWon 於 2004/05/12 14:13:45
------
老王 |
TATSU
版主 發表:50 回覆:135 積分:62 註冊:2003-01-16 發送簡訊給我 |
|
LargeWon
一般會員 發表:3 回覆:10 積分:2 註冊:2002-12-24 發送簡訊給我 |
|
TATSU
版主 發表:50 回覆:135 積分:62 註冊:2003-01-16 發送簡訊給我 |
就以按下 Listview column header 去排序,如果是單單一個 column 的排序,
寫多少少程式碼也不是大問題,但如果是多於一個 column 的排序,我會選擇
再做一次 query (SELECT ...... ORDER BY DEPT_NAME DESC, USER_NAME) ,
總會較寫一個 TList 的排序簡單及快捷。 至於你提到的記下 selected 及 focused item 的問題,我沒有測試過,但如果
轉成這樣,又是否可以操作? ListView1.Items[i].Selected := True ;
ListView1.Items[i].Focused := True ; 當然,如果 ListView1.SelCount > 0 時,你要先記下某一(些)item ,排序
後,又要找出那(些)item ,然後再設定 selected 及 focused 。你再試試吧
! 離線閱讀程式
|
LargeWon
一般會員 發表:3 回覆:10 積分:2 註冊:2002-12-24 發送簡訊給我 |
我现在是多Column排序,当然不能重做Query了(数据是否来自数据库还不一定呢,何况还会产生网络传送的问题),现准备重做TListView的Sort方法。
ListView1.Items[i].Selected := True ; ListView1.Items[i].Focused := True ; ListView1.Selected := lvDetail.Items[I]; ListView1.ItemFocused := lvDetail.Items[I]; //这四种方法都不能正确执行,不知道是否还有其他解决方法 ListView1.Items[I].MakeVisible(True/False);也无执行效果老王 發表人 - LargeWon 於 2004/05/13 13:45:08
------
老王 |
TATSU
版主 發表:50 回覆:135 積分:62 註冊:2003-01-16 發送簡訊給我 |
引言: 我现在是多Column排序,当然不能重做Query了(数据是否来自数据库还不一定呢,何G还?产生网络传送的问题),现准?重做TListView的Sort方法。ListView 有一個 property : HideSelection ,原始值為 True,這樣的情況 下,如果你的 ListView 不是 Focused ,selection 是不會顯示,你改為 False ,然後你再試 ListView1.Items[i].Selected := True ; ListView1.Items[i].Focused := True ; 應該可以做到的。 離線閱讀程式ListView1.Selected := lvDetail.Items[I]; ListView1.ItemFocused := lvDetail.Items[I]; //这四种方法都不能正确执行,不知道是否还有其他解?方法 ListView1.Items[I].MakeVisible(True/False);也?执行效果老王 發表人 - LargeWon 於 2004/05/13 13:45:08 |
LargeWon
一般會員 發表:3 回覆:10 積分:2 註冊:2002-12-24 發送簡訊給我 |
|
SuperLowB
初階會員 發表:96 回覆:77 積分:34 註冊:2003-06-11 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |