Delphi XE5でFireMonkeyのグリッドのセルの背景に画像を表示できたので作業の記録をまとめました。
グリッドのセルはTStyledControlクラス
グリッドのセルはTStyledControlクラスで構成されます。
TStyledControlクラスの派生クラスであるTEdit・TCheckBox・TProgressBar・TPopupBox・TImageControlなどのクラスは、グリッドのセルに使用できます。
今回は、TImageCellの上にTEditを配置したクラスをセルに使用することにします。
type
/// <summary>
/// 背景に画像を表示するセル
/// </summary>
TImageEditCell = class(TImageCell)
private
FEdit: TEdit;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
constructor TImageEditCell.Create(AOwner: TComponent);
begin
inherited;
Self.EnableOpenDialog := False;
FEdit := TEdit.Create(Self);
FEdit.Parent := Self;
FEdit.Align := TAlignLayout.alClient;
end;
destructor TImageEditCell.Destroy;
begin
FreeAndNil(FEdit);
inherited;
end;
セルのDataプロパティを通してグリッドとセルは値をやりとりする
セルのDataプロパティを通してグリッドとセルは値をやりとりします。
セルの持つ情報を表現するクラスを作成します。
少し長いですが、単純なクラスなので全文を掲載します。
type
/// <summary>
/// TImageEditCellの値を表現するクラス
/// </summary>
TImageEditCellData = class(TPersistent)
private
/// <summary>
/// セルに表示する文字列
/// </summary>
FText: string;
/// <summary>
/// セルの背景画像
/// </summary>
FBitmap: TBitmap;
public
constructor Create; overload;
/// <param name="Text">
/// セルに表示する文字列
/// </param>
/// <param name="Path">
/// セルの背景画像のファイルのパス
/// </param>
constructor Create(Text, Path: string); overload;
destructor Destroy; override;
/// <summary>
/// 値をコピーする
/// </summary>
procedure Assign(Source: TPersistent); override;
published
/// <summary>
/// Editに表示する文字列
/// </summary>
property Text: string read FText write FText;
/// <summary>
/// TImageCellに表示する画像
/// </summary>
property Bitmap: TBitmap read FBitmap write FBitmap;
end;
{ TImageEditCellData }
procedure TImageEditCellData.Assign(Source: TPersistent);
var
Data: TImageEditCellData;
begin
if Source is TImageEditCellData then
begin
Data := Source as TImageEditCellData;
FText := Data.Text;
FBitmap.Assign(Data.Bitmap);
end;
end;
constructor TImageEditCellData.Create;
begin
FBitmap := TBitmap.Create;
end;
constructor TImageEditCellData.Create(Text, Path: string);
begin
FBitmap := TBitmap.Create;
FText := Text;
FBitmap.LoadFromFile(Path);
end;
destructor TImageEditCellData.Destroy;
begin
FreeAndNil(FBitmap);
inherited;
end;
Dataプロパティは次のように定義されていて、値の取得や設定の時にはGetDataメソッド・SetDataメソッドが呼び出されます。
property Data: TValue read GetData write SetData;
TImageEditCellのDataプロパティでTImageEditCellDataクラスをやりとりするようにします。
/// <summary>
/// 背景に画像を表示するセル
/// </summary>
TImageEditCell = class(TImageCell)
private
…
FImageTextCellData: TImageEditCellData;
protected
function GetData: TValue; override;
procedure SetData(const Value: TValue); override;
public
…
end;
constructor TImageEditCell.Create(AOwner: TComponent);
begin
…
FImageTextCellData := TImageEditCellData.Create;
end;
destructor TImageEditCell.Destroy;
begin
FreeAndNil(FImageTextCellData);
…
end;
function TImageEditCell.GetData: TValue;
begin
Result := FImageTextCellData;
end;
procedure TImageEditCell.SetData(const Value: TValue);
begin
if Value.IsType<TImageEditCellData> then
begin
FImageTextCellData.Assign(Value.AsType<TImageEditCellData>);
FEdit.Text := FImageTextCellData.Text;
Self.Bitmap.Assign(FImageTextCellData.Bitmap);
end;
end;
とりあえず、セルに値を設定する機能だけ実装しました。
セルのオブジェクトはTColumnクラスのCreateCellControlメソッドで生成する
セルのオブジェクトはTColumnクラスのCreateCellControlメソッドで生成します。
CreateCellControlメソッドでTImageEditCellクラスを返すTColumnクラスの派生クラスを作成します。
type
/// <summary>
/// セルにTImageEditCellを使う列クラス
/// </summary>
TImageEditColumn = class(TColumn)
protected
function CreateCellControl: TStyledControl; override;
public
constructor Create(AOwner: TComponent); override;
end;
constructor TImageEditColumn.Create(AOwner: TComponent);
begin
inherited;
end;
function TImageEditColumn.CreateCellControl: TStyledControl;
begin
Result := TImageEditCell.Create(Self);
end;
TGridクラスのAddObjectメソッドで列クラスを登録する
作成した列クラスをグリッドに登録します。
フォームにTGridを配置し、フォームのOnCreateイベントでグリッドの設定を行います。
procedure TForm1.FormCreate(Sender: TObject);
begin
Grid1.RowCount := 5;
Grid1.RowHeight := 64;
Grid1.AddObject(TImageEditColumn.Create(Grid1));
end;
TGridクラスのOnGetValueイベントで、セルの値を設定する
TGridクラスのOnGetValueイベントで、セルの値を設定します。
まずセルに表示する値を保持する変数を作成します。
type
TForm1 = class(TForm)
…
private
{ private 宣言 }
FCellDataList: TObjectList<TImageEditCellData>;
…
end;
フォームのOnCreateイベントでセルに表示する値を作成します。
procedure TForm1.FormCreate(Sender: TObject);
begin
…
FCellDataList := TObjectList<TImageEditCellData>.Create;
FCellDataList.Add(TImageEditCellData.Create('arrow_left_64.bmp',
'C:\data\arrow_left_64.bmp'));
FCellDataList.Add(TImageEditCellData.Create('arrow_right_64.bmp',
'C:\data\arrow_right_64.bmp'));
FCellDataList.Add(TImageEditCellData.Create('clipboard_copy_lined_64.bmp',
'C:\data\clipboard_copy_lined_64.bmp'));
FCellDataList.Add(TImageEditCellData.Create('clipboard_cut_64.bmp',
'C:\data\clipboard_cut_64.bmp'));
FCellDataList.Add(TImageEditCellData.Create('clipboard_paste_lined_64.bmp',
'C:\data\clipboard_paste_lined_64.bmp'));
end;
グリッドのOnGetValueイベントで、セルの値を設定します。
procedure TForm1.Grid1GetValue(Sender: TObject; const Col, Row: Integer;
var Value: TValue);
begin
if Col = 0 then
Value := FCellDataList[Row];
end;
セルの背景を透過する
ここまでのプログラムを実行すると、セルの背景画像が表示されません。
TImageEditCellクラスのTEditの背景が白色になっているため、TEditの下にあるTImageCellが見えなくなっています。
背景が透明なTEditのサブクラスを作成します。
type
/// <summary>
/// 背景が透明なTEdit
/// </summary>
TTransparentEdit = class(TEdit)
protected
procedure ApplyStyle; override;
end;
{ TTransparentEdit }
procedure TTransparentEdit.ApplyStyle;
var
Obj: TFmxObject;
begin
inherited;
Obj := FindStyleResource('background');
if Assigned(Obj) then
begin
TControl(Obj).Opacity := 0;
end;
end;
TEditではなく、作成したTTransparentEditクラスを使うように修正します。
constructor TImageEditCell.Create(AOwner: TComponent);
var
Obj: TFmxObject;
begin
inherited;
Self.EnableOpenDialog := False;
FEdit := TTransparentEdit.Create(Self); //TEditをTTransparentEditに変更
FEdit.Parent := Self;
FEdit.Align := TAlignLayout.alClient;
FImageTextCellData := TImageEditCellData.Create;
end;
これで入力欄の背景が透明になり、画像が表示されるようになりました。
最後に
今回は表示だけで、入力のことは考慮していません。
実際に使用するにはいろいろと修正が必要かもしれません。
最後にソースコード全文を掲載します。
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.Layouts, FMX.Grid, FMX.Edit, System.Generics.Collections;
type
/// <summary>
/// TImageEditCellの値を表現するクラス
/// </summary>
TImageEditCellData = class(TPersistent)
private
/// <summary>
/// セルに表示する文字列
/// </summary>
FText: string;
/// <summary>
/// セルの背景画像
/// </summary>
FBitmap: TBitmap;
public
constructor Create; overload;
/// <param name="Text">
/// セルに表示する文字列
/// </param>
/// <param name="Path">
/// セルの背景画像のファイルのパス
/// </param>
constructor Create(Text, Path: string); overload;
destructor Destroy; override;
/// <summary>
/// 値をコピーする
/// </summary>
procedure Assign(Source: TPersistent); override;
published
/// <summary>
/// Editに表示する文字列
/// </summary>
property Text: string read FText write FText;
/// <summary>
/// TImageControlに表示する画像
/// </summary>
property Bitmap: TBitmap read FBitmap write FBitmap;
end;
/// <summary>
/// 背景が透明なTEdit
/// </summary>
TTransparentEdit = class(TEdit)
protected
procedure ApplyStyle; override;
end;
/// <summary>
/// 背景に画像を表示するセル
/// </summary>
TImageEditCell = class(TImageCell)
private
FEdit: TEdit;
FImageTextCellData: TImageEditCellData;
protected
function GetData: TValue; override;
procedure SetData(const Value: TValue); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
/// <summary>
/// セルにTImageEditCellを使う列クラス
/// </summary>
TImageEditColumn = class(TColumn)
protected
function CreateCellControl: TStyledControl; override;
public
constructor Create(AOwner: TComponent); override;
end;
type
TForm1 = class(TForm)
Grid1: TGrid;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Grid1GetValue(Sender: TObject; const Col, Row: Integer;
var Value: TValue);
private
{ private 宣言 }
public
{ public 宣言 }
FCellDataList: TObjectList<TImageEditCellData>;
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
{ TImageEditCell }
constructor TImageEditCell.Create(AOwner: TComponent);
var
Obj: TFmxObject;
begin
inherited;
Self.EnableOpenDialog := False;
FEdit := TTransparentEdit.Create(Self);
FEdit.Parent := Self;
FEdit.Align := TAlignLayout.alClient;
FImageTextCellData := TImageEditCellData.Create;
end;
destructor TImageEditCell.Destroy;
begin
FreeAndNil(FImageTextCellData);
FreeAndNil(FEdit);
inherited;
end;
function TImageEditCell.GetData: TValue;
begin
Result := FImageTextCellData;
end;
procedure TImageEditCell.SetData(const Value: TValue);
begin
if Value.IsType<TImageEditCellData> then
begin
FImageTextCellData.Assign(Value.AsType<TImageEditCellData>);
FEdit.Text := FImageTextCellData.Text;
Self.Bitmap.Assign(FImageTextCellData.Bitmap);
end;
end;
{ TImageEditCellData }
procedure TImageEditCellData.Assign(Source: TPersistent);
var
Data: TImageEditCellData;
begin
if Source is TImageEditCellData then
begin
Data := Source as TImageEditCellData;
FText := Data.Text;
FBitmap.Assign(Data.Bitmap);
end;
end;
constructor TImageEditCellData.Create;
begin
FBitmap := TBitmap.Create;
end;
constructor TImageEditCellData.Create(Text, Path: string);
begin
FBitmap := TBitmap.Create;
FText := Text;
FBitmap.LoadFromFile(Path);
end;
destructor TImageEditCellData.Destroy;
begin
FreeAndNil(FBitmap);
inherited;
end;
{ TImageEditColumn }
constructor TImageEditColumn.Create(AOwner: TComponent);
begin
inherited;
end;
function TImageEditColumn.CreateCellControl: TStyledControl;
begin
Result := TImageEditCell.Create(Self);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Grid1.RowCount := 5;
Grid1.RowHeight := 64;
Grid1.AddObject(TImageEditColumn.Create(Grid1));
FCellDataList := TObjectList<TImageEditCellData>.Create;
FCellDataList.Add(TImageEditCellData.Create('arrow_left_64.bmp',
'C:\data\arrow_left_64.bmp'));
FCellDataList.Add(TImageEditCellData.Create('arrow_right_64.bmp',
'C:\data\arrow_right_64.bmp'));
FCellDataList.Add(TImageEditCellData.Create('clipboard_copy_lined_64.bmp',
'C:\data\clipboard_copy_lined_64.bmp'));
FCellDataList.Add(TImageEditCellData.Create('clipboard_cut_64.bmp',
'C:\data\clipboard_cut_64.bmp'));
FCellDataList.Add(TImageEditCellData.Create('clipboard_paste_lined_64.bmp',
'C:\data\clipboard_paste_lined_64.bmp'));
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FCellDataList.Free;
end;
procedure TForm1.Grid1GetValue(Sender: TObject; const Col, Row: Integer;
var Value: TValue);
begin
if Col = 0 then
Value := FCellDataList[Row];
end;
{ TTransparentEdit }
procedure TTransparentEdit.ApplyStyle;
var
Obj: TFmxObject;
begin
inherited;
Obj := FindStyleResource('background');
if Assigned(Obj) then
begin
TControl(Obj).Opacity := 0;
end;
end;
end.
変更履歴
- 2013年11月2日
入力欄の背景を透明にする方法をカスタムスタイを使った方法から、背景が透明なTEditのサブクラスを使用する方法に変更しました。