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方法可以使用....纠结啊