使用虚拟方法
将Style
ListBox 的属性设置为lbVirtual
,并分配OnData
事件以使其请求绘制控件所需的字符串,而不是拥有在每次更新时重置整个控件的字符串。说明性代码:
unit Unit1;
interface
uses
Windows, Messages, Classes, Controls, Forms, AppEvnts, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
ApplicationEvents1: TApplicationEvents;
ListBox1: TListBox;
Timer1: TTimer;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ListBox1Data(Control: TWinControl; Index: Integer;
var Data: String);
procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
procedure Timer1Timer(Sender: TObject);
private
FStrings: TStringList;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FStrings := TStringList.Create;
FStrings.CommaText := 'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z';
ListBox1.Count := FStrings.Count;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FStrings.Free;
end;
procedure TForm1.ListBox1Data(Control: TWinControl; Index: Integer;
var Data: String);
begin
Data := FStrings[Index];
end;
procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
begin
FStrings[Random(FStrings.Count)] := Chr(65 + Random(26));
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
ListBox1.Invalidate;
end;
end.
在此示例中,我使用组件的OnIdle
事件TApplicationEvents
来模拟您对 StringList 的线程更新。请注意,您现在可以滚动和选择 ListBox 中的项目,尽管 Timer 的更新间隔为 1 秒。
同步项目计数
StringList 的项目计数的变化也需要反映在 ListBox 中。这需要由 来完成ListBox1.Count := FStrings.Count
,但是 ListBox 的外观将再次被重置。因此,需要一种解决方法,暂时阻止它一起重绘/更新:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if Random(2) = 0 then
begin
FStrings.Add('A');
SyncListCounts;
end
else
ListBox1.Invalidate;
end;
procedure TForm1.SyncListCounts;
var
SaveItemIndex: Integer;
SaveTopIndex: Integer;
begin
ListBox1.Items.BeginUpdate;
try
SaveItemIndex := ListBox1.ItemIndex;
SaveTopIndex := ListBox1.TopIndex;
ListBox1.Count := FStrings.Count;
ListBox1.ItemIndex := SaveItemIndex;
ListBox1.TopIndex := SaveTopIndex;
finally
ListBox1.Items.EndUpdate;
end;
end;