全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2532
推到 Plurk!
推到 Facebook!

能增加ListView讀取速度嗎?

答題得分者是:TATSU
HomeSound
中階會員


發表:44
回覆:178
積分:94
註冊:2002-08-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-04-02 17:05:08 IP:61.30.xxx.xxx 未訂閱
ListView->Items->BeginUpdate();
for(int i=1;i < RichEdit->Lines->Count;i  )
{ 
  ListItem = ListView->Items->Add();
  ListItem->Caption=tmp.sprintf("d",i);
  ListItem->SubItems->Add(tmp.sprintf("d",i));
  RichEdit->SelStart=SendMessage(RichEdit->Handle,EM_LINEINDEX,i,0);
  RichEdit->SelLength=RichEdit->Lines->Strings[i].Length();
  Section=RichEdit->SelText;
  ListItem->SubItems->Add(Section.SubString(38,25));
  ListItem->SubItems->Add(Section.SubString(26,2));
  ListItem->SubItems->Add(Section.SubString(21,4));
  ListItem->SubItems->Add(Section.SubString(9,11));
  ListItem->SubItems->Add(Section.SubString(1,8));
  ListItem->SubItems->Add(Section.SubString(25,1));
  ListItem->SubItems->Add(Section.SubString(29,8));
  ListItem->SubItems->Add(Section.SubString(28,1));
  ListItem->SubItems->Add(Section.SubString(64,58));
  ListItem->SubItems->Add(Section.SubString(20,1));
}
ListView->Items->EndUpdate();
如上迴圈 再Win98上Run的話,加入2000行約兩秒鐘,但移到WinXP上Run要20秒左右 才能跑完,小弟程式是於Win98 BCB5.0上編譯的,不知為何會這樣
------
--==多看.多學.多聽==--
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-04-11 09:50:08 IP:211.76.xxx.xxx 未訂閱
這是之前討論過關於 TStringList 速度的問題 ■ 讀取文字檔的速度 LoadFromFile()  http://delphi.ktop.com.tw/topic.php?topic_id=19925    關於您的問題,如果您已確定要加入多少行,可以先將 Capacity 的屬性設大,避免記憶體重配置的問題,看看可不可以提高速度。    沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
HomeSound
中階會員


發表:44
回覆:178
積分:94
註冊:2002-08-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-04-11 17:06:07 IP:61.30.xxx.xxx 未訂閱
感謝dllee大人回答,小弟早已用AllocBy=4000,如果把回圈內的Add() 都先拿掉是很快,一樣也是慢在ADD()上,真不知道Win98跟WinXP的 ListView差在那兒,目前是先加上
------
--==多看.多學.多聽==--
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-04-12 15:18:02 IP:220.139.xxx.xxx 未訂閱
引言: 一樣也是慢在ADD()上,真不知道Win98跟WinXP的 ListView差在那兒 < face="Verdana, Arial, Helvetica"> 差在系統不一樣,因為 BCB/Delphi 也是叫用 Windows 系統提供的元件,只是幫我們包裝成 VCL 而已。 想要快的話,只能自己再加一些處理,例如不要全部都顯示,只顯示使用者看得到的部分等等,大部分慢都慢在記憶體重新配置以及顯示,避免不必要的記憶體重新配置及顯示,速度就能提升。 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
TATSU
版主


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

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-04-12 22:24:42 IP:203.218.xxx.xxx 未訂閱
如果你會 Delphi ,可以看看以下程式碼,我其實很少用 TreeView, ListView ,我最常用的是 Virtual TreeView ,因為實在快,至於你的問題,其實可以用到以下方法,不過我不會 C++,如果你會 Delphi ,應該明白這段程式做什麼。    
unit Unit1;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;    type
  PTxtLines = ^TTxtLines ;
  TTxtLines = Record
    Lines : String ;
  end;
  TForm1 = class(TForm)
    edtFilename: TEdit;
    btnGetFile: TButton;
    OpenDialog1: TOpenDialog;
    edtLines: TEdit;
    btnStandard: TButton;
    lblStandard: TLabel;
    lvStandard: TListView;
    lvVirtual: TListView;
    btnVirtual: TButton;
    lblVirtual: TLabel;
    procedure btnGetFileClick(Sender: TObject);
    procedure btnStandardClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure btnVirtualClick(Sender: TObject);
    procedure lvVirtualData(Sender: TObject; Item: TListItem);
  private
    { Private declarations }
    LineList : TList ;
    procedure ClearTxtLines ;
  public
    { Public declarations }
  end;    var
  Form1: TForm1;    implementation    {$R *.dfm}    procedure TForm1.btnGetFileClick(Sender: TObject);
begin
  if OpenDialog1.Execute then
    edtFilename.Text := OpenDialog1.FileName ;
end;    procedure TForm1.btnStandardClick(Sender: TObject);
var
  nTotal, nLines : Integer ;
  cLine : String ;
  F1 : TextFile ;
  LineItem : TListItem ;
  tStart, tEnd : TDateTime ;
begin
  if FileExists(edtFilename.Text) then
  begin
    tStart := Now ;
    nTotal := StrToInt(edtLines.Text) ;
    nLines := 0 ;
    AssignFile(F1, edtFileName.Text) ;
    Reset(F1) ;
    lvStandard.Items.BeginUpdate ;
    lvStandard.items.clear ;
    while Not(Eof(F1)) do
    begin
      inc(nLines) ;
      ReadLn(F1, cLine) ;
      LineItem := lvStandard.Items.Add ;
      LineItem.Caption := cLine ;
      if nLines = nTotal then break ;
    end;
    lvStandard.Items.EndUpdate ;
    CloseFile(F1) ;
    tEnd := Now ;
    lblStandard.Caption := FormatDateTime('hh:mm:ss.zzz', tEnd - tStart) ;
  end;
end;    procedure TForm1.FormCreate(Sender: TObject);
begin
  LineList := TList.Create ;
end;    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ClearTxtLines ;
  LineList.Free ;
end;    procedure TForm1.btnVirtualClick(Sender: TObject);
var
  nTotal, nLines : Integer ;
  cLine : String ;
  F1 : TextFile ;
  LineItem : TListItem ;
  tStart, tEnd : TDateTime ;
  aRecord : PTxtLines ;
begin
  if FileExists(edtFilename.Text) then
  begin
    tStart := Now ;
    nTotal := StrToInt(edtLines.Text) ;
    nLines := 0 ;
    AssignFile(F1, edtFilename.Text) ;
    Reset(F1) ;
    ClearTxtLines ;
    while Not(Eof(F1)) do
    begin
      inc(nLines) ;
      ReadLn(F1, cLine) ;
      New(aRecord) ;
      aRecord.Lines := cLine ;
      LineList.Add(aRecord) ;
      if nLines = nTotal then break ;
    end;
    CloseFile(F1) ;
    tEnd := Now ;
    lvVirtual.Items.Count := nTotal ; //<== 讓 ListView 知道有多少筆資料
    lvVirtual.Invalidate ; 
    lblVirtual.Caption := FormatDateTime('hh:mm:ss.zzz', tEnd - tStart) ;
  end;
end;    procedure TForm1.lvVirtualData(Sender: TObject; Item: TListItem);
begin
  if Item.Index < LineList.Count then
  begin
    // 因應這個 Item 的 Index 由已讀取資料的 list 內抓取字串
    Item.Caption := PTxtLines(LineList.Items[Item.Index]).Lines ;
  end;
end;    procedure TForm1.ClearTxtLines ;
var
  i : integer ;
begin
  if LineList.Count > 0 then
  begin
    for i := 0 to (LineList.Count - 1) do
      Dispose(PTxtLines(LineList.Items[i])) ;
  end;
  LineList.Clear ;
end;    end.    
執行這一支程式時,我找了 mysql.txt ,一個十分大的檔案,載入 20,000 行,使用基本 ListView 就要用 30 秒,但用上 ownerdata ,將每一行的文字都存到 TList 內一個自訂的資料類型內,就只需要用 0.161 秒,它只是花時間去讀檔案,沒有實質的資料加到 Listview 去儲存,要找資料時,你便要提供一筆資料給它。你如果當中沒有什麼花俏的東東,你可以用上這個方法,多大的文字檔也可以十分快的速度秀出。 20,000 行:30.013, 0.161 秒 50,000 行:3:46.285, 0.351 秒 因為你的一篇舊文章,我再翻看 ListBox 一些資料,兩者基本上都可以用到這個方法,只差是用那一種方法去讀取文字檔及儲存類型,但一定不是放到 Listview 或 Listbox 的內部儲存。 Listbox.style := lbVirtual ; Listbox.count := xx // no. of lines ListBox.OnData event ListView.OwnerData := True ; ListView.Items.Count := xx //no. of lines ListView.OnData event 兩者速度一致,都可以用這個方法,至於用 TList 或 TStringList 做儲存,就由你發揮。 哈哈...不會 C 的人,走到這裏回答問題... 發表人 -
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-04-14 08:07:48 IP:211.76.xxx.xxx 未訂閱
感謝 TATSU 版主, 原來 ListBox 還可以這樣用... 我立刻試一下,但發現 BCB5 沒有此 style,也許 BCB6 應該有提供。 而 ListView 則有此功能 (我好像還沒用過它 < >),以後可能要多用用看囉 < > P.S. 我也不懂 Delphi 但有時也會到 Delphi 去走走,互相交流一下吧 <>沒空更新的網頁... href="http://dllee.adsldns.org">http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell.... 發表人 - dllee 於 2004/04/14 08:09:21
------
http://www.ViewMove.com
TATSU
版主


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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-04-14 13:01:55 IP:219.76.xxx.xxx 未訂閱
引言: 感謝 TATSU 版主, 原來 ListBox 還可以這樣用... 我立刻試一下,但發現 BCB5 沒有此 style,也許 BCB6 應該有提供。 而 ListView 則有此功能 (我好像還沒用過它 < >),以後可能要多用用看囉 < > P.S. 我也不懂 Delphi 但有時也會到 Delphi 去走走,互相交流一下吧 <>沒空更新的網頁... href="http://dllee.adsldns.org">http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell.... 發表人 - dllee 於 2004/04/14 08:09:21
因為不懂 C ,只可以提供一個原理,希望可以幫到你們解決問題。
系統時間:2024-05-14 16:17:01
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!