線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2182
推到 Plurk!
推到 Facebook!

如何解决向TListView加入大量数据产生的速度问题

尚未結案
LargeWon
一般會員


發表:3
回覆:10
積分:2
註冊:2002-12-24

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-05-11 15:05:25 IP:211.162.xxx.xxx 未訂閱
问题产生:我向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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-05-11 15:21:33 IP:218.80.xxx.xxx 未訂閱
Data := Self;     Caption := FACaption;     SubItems.Capacity:=2; SubItems.Add(ParentID);//最耗时代码,使用SubItems.BeginUpdate/EndUpdate也不能解决 SubItems.Add(ID);//最耗时代码 久病成良医--多试 千人之诺诺,不如一士之谔谔--兼听
------
江上何人初见月,江月何年初照人
Chance36
版主


發表:31
回覆:1033
積分:792
註冊:2002-12-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-05-11 16:43:54 IP:203.204.xxx.xxx 未訂閱
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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-05-11 16:52:57 IP:218.102.xxx.xxx 未訂閱
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

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-05-12 13:45:14 IP:211.162.xxx.xxx 未訂閱
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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-05-12 14:43:52 IP:218.102.xxx.xxx 未訂閱
不論是 ListBox 或 ListView ,數量過千,更新的速度必定會慢下來,使 用 Virtual List 的方法是最直接及有效,如果你可以提供一個模擬的  MS-ACCESS 的數據庫,我還可以幫你測試。    離線閱讀程式
LargeWon
一般會員


發表:3
回覆:10
積分:2
註冊:2002-12-24

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-05-12 15:27:45 IP:211.162.xxx.xxx 未訂閱
TATSU 的方法我测试过,速度很快。但我以上回复的是按你的方法后产生的新问题,而这些问题是必须解决掉的,否则使用此方法所要付出的代价就太大了。 老王
------
老王
TATSU
版主


發表:50
回覆:135
積分:62
註冊:2003-01-16

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-05-12 17:23:59 IP:218.102.xxx.xxx 未訂閱
就以按下 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

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-05-13 09:02:58 IP:211.162.xxx.xxx 未訂閱
我现在是多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

發送簡訊給我
#10 引用回覆 回覆 發表時間:2004-05-13 18:36:39 IP:218.102.xxx.xxx 未訂閱
引言: 我现在是多Column排序,当然不能重做Query了(数据是否来自数据库还不一定呢,何G还?产生网络传送的问题),现准?重做TListView的Sort方法。
  ListView1.Selected := lvDetail.Items[I];
  ListView1.ItemFocused := lvDetail.Items[I];
  //这四种方法都不能正确执行,不知道是否还有其他解?方法
  ListView1.Items[I].MakeVisible(True/False);也?执行效果
老王 發表人 - LargeWon 於 2004/05/13 13:45:08
ListView 有一個 property : HideSelection ,原始值為 True,這樣的情況 下,如果你的 ListView 不是 Focused ,selection 是不會顯示,你改為 False ,然後你再試 ListView1.Items[i].Selected := True ; ListView1.Items[i].Focused := True ; 應該可以做到的。 離線閱讀程式
LargeWon
一般會員


發表:3
回覆:10
積分:2
註冊:2002-12-24

發送簡訊給我
#11 引用回覆 回覆 發表時間:2004-05-14 17:01:25 IP:211.162.xxx.xxx 未訂閱
对不起,应该是我自己弄错了,我在仔细看看。 發表人 - LargeWon 於 2004/05/14 17:27:11
------
老王
SuperLowB
初階會員


發表:96
回覆:77
積分:34
註冊:2003-06-11

發送簡訊給我
#12 引用回覆 回覆 發表時間:2004-05-17 17:50:50 IP:203.198.xxx.xxx 未訂閱
但是如果想加入checkbox在最左邊......好像不行....好像是給ListView1.OwnerData累了
系統時間:2024-06-15 18:43:58
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!