加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – TListBox与TStringList同步

发布时间:2020-12-15 04:23:39 所属栏目:大数据 来源:网络整理
导读:我有一个后台线程向主线程发送消息,反过来,它将消息添加到TListBox,如日志. 事实是,这个后台线程非常快,我真的不需要快速更新日志.我想将消息添加到TStringList并设置一个计时器来每秒更新TListBox. 我尝试过使用: listBox1.Items := StringList1; 要么 lis
我有一个后台线程向主线程发送消息,反过来,它将消息添加到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;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读