XE中FMX操作ListBox,添加上千条记录(含图片)

我之前是想在ListBox的每个Item上添加一个图片,Item上所有的内容都是放在Object里赋值,结果发现加载一百条记录耗时四五秒:

procedure TMainForm.AddItem;
var
  o  : TListBoxItem;
  o1 : TFrm;
begin
  o := TListBoxItem.Create(self);     // 创建对象
  o.Height := 128;
  o1 :=TFrm.Create(o);                 // 创建TFrm
  o1.Parent:=o;
  ListBox1.AddObject(o);
end;

var
  s, temp: string;
  x: IMember;
begin
  if FJV <> Value then begin
    FJV := Value;
    for x in Value do begin          // x为遍历所有Item框架上的组件的值
      s := x.AsString;
      if x.Name = 'IPNR'        then IPNR     .Text := s else
      if x.Name = 'IPNColor'    then IPNColor .Text := s else
      if x.Name = 'ITime'       then ITime    .Text := s else
      if x.Name = 'OTime'       then OTime    .Text := s else
      if x.Name = 'PName'       then PName    .Text := s else
      if x.Name = 'IGateName'   then IGateName.Text := s else
      if x.Name = 'OGateName'   then OGateName.Text := s else
      if x.Name = 'IMobileNo'   then IMobileNo.Text := s else
      if x.Name = 'State'       then timer1.Enabled := True;
      ;
      end;
end;
这里加载图片,我还是用线程异步加载的,速度还是不行:
procedure TMainForm.DrawImg();
var
  i: integer;
  o: TImage;
  fn:string;
begin
  // 取
  TThread.CreateAnonymousThread(procedure var y : IMember; begin
    i:=length(bmps);
    if(i<>FNs.Count)and(FNs.Count>0) then begin
      SetLength(bmps,FNs.Count);
      for y in FNs do if y.AsInteger=-1 then begin
        bmps[i]:=TBitmap.CreateFromFile(y.Name);
        FNs.I[y.Name]:=i;
        inc(i);
      end;
    end;
    // 显示
    TThread.Synchronize(TThread.CurrentThread, procedure var z: IMember; begin
      i:=0;
      for z in JV do begin
        o :=TFrm(ListBox1.ListItems[i].FindComponent('Frm')).Image1;
        fn:=z.AsObject.S['IImagePath'];
        o.Visible := FNs.Contains(fn);
        if(o.Visible) then o.Bitmap.Assign(bmps[FNs.I[fn]]);
        inc(i);
      end;
    end);
  end).Start;
end;

然后我将图片压缩,压缩后倒是快了那么一两秒,但是如果数据量大的话,还是有很明显的延迟效果:

uses Vcl.Imaging.jpeg;

{fn1为压缩前的图片路径,fn2为压缩后的图片路径} procedure CutImg(fn1:string; fn2:string); var jpg: TJpegImage; bmp: TBitmap; begin jpg := TJpegImage.Create; bmp := TBitmap.Create; try if FileExists(fn1) then begin jpg.LoadFromFile(fn1); if jpg.Width > 320 then begin bmp.Width := 320; //jpg.Width; 经测试的宽度 bmp.Height:= 256; //jpg.Height; bmp.Canvas.StretchDraw(bmp.Canvas.ClipRect, jpg); jpg.Assign(bmp); jpg.CompressionQuality := 30; jpg.Compress; //压缩 jpg.SaveToFile(fn2); end; end; finally bmp.Free; jpg.Free; end; end;

最后通过别人那里知道XE中ListBox有style模板,看XE自带的原码,目录在C:\Users\Public\Documents\Embarcadero\Studio\14.0\Samples\Object Pascal\FireMonkey Desktop\CustomListBox\CustomListBox.dpr;

这个例子就是导入一千条记录,简直就只需要一秒,速度太快了,XE支持这个功能真是太好了。然后我把之前的框架换成了style(style用XE6还是有很多bug的,后来我换成了XE8,这里自己摸),速度提高了几倍:

 for x in jo do with item do begin
    s := x.AsString.Replace('/', '\');
    if x.Name = 'IPNR'        then StylesData['IPNR.Text'      ] := s else
    if x.Name = 'IPNColor'    then StylesData['IPNColor.text'  ] := s else
    if x.Name = 'ITime'       then StylesData['ITime.text'     ] := s else
    if x.Name = 'OTime'       then StylesData['OTime.text'     ] := s else
    if x.Name = 'PName'       then StylesData['PName.text'     ] := s else
    if x.Name = 'IGateName'   then StylesData['IGateName.text' ] := s else
    if x.Name = 'OGateName'   then StylesData['OGateName.text' ] := s else
    if x.Name = 'IMobileNo'   then StylesData['IMobileNo.text' ] := s else
    if x.Name = 'IImagePath'  then if s <> '' then StylesData['Image1.Bitmap'  ] := bmps[s] else

bmps为TDictionary<string, TBitmap>类;需要uses  Generics.Collections;

这是泛型,存放一个key,和key对应的Value:

t:=1; o:=FileToStream('c:/123.jpg');

 bmps.Add(t, o);

取值时为   Image1.Bitmap := bmps[s]

这样简单了很多,少了很多代码,快了很多时间。  

posted @ 2015-09-23 22:00  王云盼  阅读(1289)  评论(0编辑  收藏  举报