delphi – TListBox与TStringList同步
我有一个后台线程向主线程发送消息,反过来,它将消息添加到TListBox,如日志.
事实是,这个后台线程非常快,我真的不需要快速更新日志.我想将消息添加到TStringList并设置一个计时器来每秒更新TListBox. 我尝试过使用: listBox1.Items := StringList1; 要么 listBox1.Items.Assign(StringList1); 在OnTimer事件中,它的工作原理.事实是,它永远不会让用户真正滚动或点击列表框,因为它每秒刷新一次. 我正在使用Delphi XE4 是否有更优雅的方式将列表框的内容与此背景StringList(或必要时的任何其他列表)同步?先感谢您! 解决方法
使用虚拟方法
将ListBox的Style属性设置为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. 在此示例中,我使用TApplicationEvents组件的OnIdle事件来模拟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; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |