TListViewを使い、1000件単位のデータを表示していましたが、
もう少し速度を向上させたいと思い、仮想リストビューを使うこ
とにしました。
その使い方について質問させてください。
●要件
①TStringListに入っている各文字列に基づき、ListView1にデータ
を表示する。
(具体的には、OwnerDataをTrueにした後、OnDataイベントで、
Item.Caption := StringList1.Strings[Item.Index]
などとしています。表示形式はvsReportです。)
②Button1を押したときには、ListView1の内容をクリアする。
●質問したい内容
上の②で、ListView1の内容をクリアするとき、下のようにして
います。
ListView1.Items.BeginUpdate;
ListView1.Items.Count := 0;
StringList1.Text := ''; // StringList.Clearだと時間がかかったため置き換えた。
ListView1.Items.EndUpdate;
ここで、
ListView1.Items.Clear;
という一文を入れていないのですが、正しいのでしょうか?
もし必要だとすれば、ListView1.Items.Count := 0;
の前に入れる必要があるのでしょうか?
ネット上のサンプルではこれが入っていましたが、これを入れると
処理が遅くなるので、必要ないなら省きたいと考えています。
まず、
StringList1.Text := '';
StringList.Clear
の速度差ですが、VCLを読めばわかることですが、
StringList1.Text := ''の方が早い事は理論的にあり得ません。
ListView1.Items.Clear;
はListView1.Itemsを全く使用していなければ不要です。
しかし、一体どれくらいの速度を要求してるんですかね?
この辺の処理はそこそこの環境ならマイクロ秒オーダーだと思いますが…
ちょっとサンプル書いてみます。
私的にはじゅうぶん早いです。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private 宣言 }
aListView:TListView;
aButton :TButton;
ListStringList : TStringList;
procedure SetData;
procedure aButtonClick(Sender: TObject);
procedure aListViewData(Sender: TObject; Item: TListItem);
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.aButtonClick(Sender: TObject);
begin
aListView.Items.Count := ListStringList.Count;
end;
procedure TForm1.aListViewData(Sender: TObject; Item: TListItem);
begin
Item.Caption := ListStringList.Strings[Item.Index];
end;
procedure TForm1.FormCreate(Sender: TObject);
var Column:TListColumn;
begin
ListStringList:= TStringList.Create;
SetData;
aListView := TListView.Create(self);
aListView.Align := alClient;
aListView.ViewStyle := vsReport;
Column:= aListView.Columns.Add;
Column.Width := 200;
aListView.OnData := aListViewData;
aListView.OwnerData:=True;
aListView.Parent := Self;
aButton := TButton.Create(Self);
aButton.Caption := 'SetData';
aButton.Anchors := [akRight,akBottom];
aButton.Left := aListView.Width - aButton.Width - 30;
aButton.Top := aListView.Height - aButton.Height - 30;
aButton.Parent := aListView;
aButton.OnClick := aButtonClick;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
aButton.Free;
aListView.Free;
ListStringList.Free;
end;
procedure TForm1.SetData;
var
DataCount,DataLen,i,p : Integer;
str,DataStr,bufstr:string;
begin
DataCount := 999999; //好きな値を入れる
DataLen := Length(InttoStr(DataCount));
bufstr := '%.' + IntToStr(DataLen) + 'd';
SetLength(str,(DataCount*DataLen + DataCount*2)*2);
for i := 1 to DataCount do
begin
DataStr := Format(bufstr,[i]);
for p := 1 to DataLen do
str[(i-1)*(DataLen+2)+p] := DataStr[p];
str[(i-1)*(DataLen+2)+DataLen+1] := #$D;
str[(i-1)*(DataLen+2)+DataLen+2] := #$A;
end;
ListStringList.Text := str;
end;
end.
SetData
//SetLength(str,(DataCount*DataLen + DataCount*2)*2);
SetLength(str,(DataCount*DataLen + DataCount*2));
バッファサイズ間違えてます。
ううう…
SetLength(str,(DataCount*(DataLen+2)));
です。
ぶっちゃけこれでok
procedure TForm1.aButtonClick(Sender: TObject);
begin
aListView.Items.Count := DataCount;
end;
procedure TForm1.aListViewData(Sender: TObject; Item: TListItem);
begin
Item.Caption := IntToStr(Item.Index);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
DataCount := 9999999;
end;
要は、TListViewよりデータ処理に時間がかかってると思います。
長いサンプルコードまで書いていただいてありがとうございます。
先ほど、こちらでもサンプルプロジェクトを作って試してみました。
膨大な件数でも一瞬で表示/消去できました。
TStringListも、単にクリアするだけなら一瞬でした。処理を切り分
けて試していたつもりですが、余計な処理が混じってしまっていたため
に時間がかかってしまっていたのだと思います。
問題としては解決ですが、とりあえず自分でももう少し処理内容の
理解をしてからチェックマークを付けさせていただきます。
本当に助かりました。どうもありがとうございました。
時間をかけて動作内容の確認等をしましたが、結果はばっちりでした。
そのため、チェックを付けさせていただきます。
改めて、どうもありがとうございました。
肝心のチェックついていませんでした(^^;)
ツイート | ![]() |