• 关于FireMonkey TGrid赋值的一点小研究


    FireMoneky的TStringGrid用法和VCL里面的差不多, 但是另一个TGrid实在是奇葩, 几乎找不到给单元格赋值的方法(除了使用LiveBind)

    看了其源码, 发现只要给某个Column.Cell.Value赋值就可以了, 但是不知道为什么 TColumn里的GetCells和SetCells这2个方法居然没有公开出来, 导致在TGrid里没有一个方法能够像StringGrid一样给某个单元格直接赋值

    继续查看源码, 发现TGrid有2个事件: OnGetValue, OnSetValue

    于是联想了一下VCL里ListView的OwnerData模式, 所以写了下面一堆代码, 勉强算是能正常使用TGrid了

      


    以下为我的测试代码:

    首先在Project->Resources and Images里添加一些资源文件, 我的测试程序里添加了11个png图

    unit Unit1;
    
    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 
      FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
      System.Rtti, FMX.Grid, FMX.Layouts;
    
    type
      TForm1 = class(TForm)
        Grid1: TGrid;
        StringColumn1: TStringColumn;
        ImageColumn1: TImageColumn;
        procedure Grid1GetValue(Sender: TObject; const Col, Row: Integer;
          var Value: TValue);
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
        FBmps: array[0..10] of TBitmap;
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.fmx}
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      i: Integer;
      nRS: TResourceStream;
    begin
      {先把资源文件都加载出来}
      for i := Low(FBmps) to High(FBmps) do
      begin
        FBmps[i] := TBitmap.Create;
        nRS := TResourceStream.Create(HInstance, pchar('PngImage_' + Inttostr(i + 1)), RT_RCDATA);
        FBmps[i].LoadFromStream(nRS);
        nRS.Free;
      end;
      TGrid
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    var
      i: Integer;
    begin
      for i := Low(FBmps) to High(FBmps) do
        FreeAndNil(FBmps[i]);
    end;
    
    procedure TForm1.Grid1GetValue(Sender: TObject; const Col, Row: Integer;
      var Value: TValue);
    begin
      if Col = 0 then
        Value := Row
      else if Col = 1 then
      begin
        Value := FBmps[Row mod 11];
      end;
    end;
    
    end.

    虽然说这样可以用, 但是我写的测试代码实际运行效果特别的卡, 估计是因为100个image列导致的, 吧TImageColumn的赋值去掉以后就非常流畅了

    究其原因, 看代码跟踪到TImageControl.SetData函数:

    procedure TImageControl.SetData(const Value: TValue);
    begin
      if Value.IsEmpty then
        Bitmap.SetSize(0, 0)
      else if (Value.IsObject) and (Value.AsObject is TPersistent) then
        Bitmap.Assign(TPersistent(Value.AsObject))
      else 
        Bitmap.LoadFromFile(Value.ToString)
    end;

     

    发现实际运行时, Grid的OnGetValue事件被触发, 给Value赋值, 然后调用TImageControl.SetData函数

    最终会执行这句: Bitmap.Assign(TPersistent(Value.AsObject))

    也就是说, 每次OnGetData一个图像列, 都要经历一次图像复制.....难怪卡的厉害

     

    个人猜测还是因为当前使用的不是正统赋值方法, 但是看代码, 又没什么public方法可以使用....纠结啊

     

  • 相关阅读:
    mescroll
    uniapp 实现常用功能拖拽
    并发之线程、进程、纤程、协程、管程与死锁,活锁
    jmeter中TPS和throughput的区别【杭州多测师】【杭州多测师_王sir】
    vite config
    s3工具awscli
    s3工具 rclone
    React错误: Can't resolve 'reactdom/client'
    React: ReactRouter嵌套路由 exact问题
    React报错:You are running `createreactapp` 5.0.0, which is behind the latest release (5.0.1).
  • 原文地址:https://www.cnblogs.com/lzl_17948876/p/3418987.html
Copyright © 2020-2023  润新知