|
DelphiXE3 [FMX] ペイントボックス(PaintBox)2013/12/27 |
前回は [Shapes]内の「画像」(Image)について見てみました。
今回は、同じく[Shapes]内の「ペイントボックス」(PaintBox)について見てみます。【DelphiXE3・VCLの記事】【Delphi2010の記事】
[Shapes]内
FMX | |
ヘルプより。
TPaintBox は、アプリケーションで画像のレンダリングに使用できるキャンバスとなる 2D 画像コンポーネントを定義します。TControl を継承しており、コントロールを作成するためのスタイルで使用できます。
TImage では、ファイルに保存されている画像を表示しますが、それとは異なり、TPaintBox では、アプリケーション側でキャンバスに直接画像を描画する必要があります。OnPaint イベントのイベント ハンドラを使用すると、ペイント ボックスの描画面である FMX.Types.TCanvas 上に描画することができます。 |
というわけで、お絵描きプログラムやCADプログラムを作る際には、おなじみのペイントボックスです。取り敢えず、Delphi2010の記事と同様のテストプログラムを記述してみます。ボタンを1つ配置して、そのクリックイベントハンドラを記述します。
procedure TForm1.Button1Click(Sender: TObject);
var
i : integer ;
begin
with PaintBox1 do begin
Canvas.BeginScene ;
Canvas.Stroke.Kind := TBrushKind.bkSolid ;
for i:=0 to Round(Height) do begin
Canvas.Stroke.Color := $FF000000 + dword(i) ;
Canvas.DrawLine(PointF(0,i),PointF(Width,i),1.0) ;
end;
Canvas.EndScene ;
end;
end; |
保存・コンパイル・実行をしてみます。
↓
VCLでの TColor値と FMXでの TAlphaColor値は、値の持ち方が違いますので、赤色系ではなく、青色系になっています。ダミーで付けたメインメニューを操作しても、別段何もせずとも、画面は乱れず現状をキープしているようです。他のアプリケーションで画面を隠しても、画面は乱れません。となると、ペイントボックスの OnPaintイベントは発動しているのでしょうか?確認してみます。
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
begin
ShowMessage('再描画');
end; |
実行すると、メッセージは最初に2回表示されますが、メインメニューで隠しても、他のアプリケーションで画面を隠しても、メッセージは表示されません。という事は、OnPaintイベントハンドラでの画面の再描画は不必要、という事になりますね。
OnPaintイベントハンドラを記述してしまうと、ペイントボックスがリサイズ出来る状況になると、悲惨な状況に陥りそうです。ペイントボックスの Alignプロパティを alLeft にして画面をリサイズしようとすると、画面を1ドット動かそうとするたびにOnPaintイベントが発動されてしまいます。それでは、OnResizeイベントハンドラを記述した場合はどうなるのでしょうか? 同じく、画面を1ドット動かそうとするたびにイベントが発動されてしまいます。フォーム画面の OnPaint、OnResizeも同様な様子です(フォーム上に配置したボタンにマウスを合わせてボタンがハイライトされるだけでOnPaintが発動してしまうので更に使い難いと思われます)。ですので、他の何らかの手法を考えた方がよさそうです。
それはさておき。
ペイントボックス PaintBox には、他のビジュアルコンポーネントにもある Canvas プロパティがあり、これに対して作図を行う、という事を行います。Canvasを操作する最初に BeginSceneメソッドを、最後に EndSceneメソッドを実行する必要があります。これは Direct2D と同じ感じなのですぐに分かると思います。Canvas には VCLとは名前や機能内容は多少違いますが、同じような、Strokeプロパティ(従来のペン)、Fillプロパティ(従来のブラシ)、Fontプロパティがあります。
実際に図形を作図するメソッドとしては、下記のようなものがあります。VCLでのWindowsGDIとは異なりますが、GDI+やDirect2D を使っていれば内容はすぐに分かると思います。
AfterConstruction public
Owner のインターフェースへの参照を取得します。
Assign public
ほかの類似オブジェクトの内容をコピーします。
BeforeDestruction public
最初のデストラクタが実行される前に応答します。
BeginScene public
描画が開始されたことを、TCanvas オブジェクトに通知します。
ClassInfo public
オブジェクト型の実行時型情報(RTTI)テーブルのポインタを返します。
ClassName public
引数で渡される変数の型ではなくオブジェクトインスタンスの型を示す文字列を返します。
ClassNameIs public
オブジェクトが指定の型かどうかを示します。
ClassParent public
1 つ上位のクラスの型を返します。
ClassType public
オブジェクトのクラスへのクラス参照を返します。
CleanupInstance public
クラス内の長い文字列とバリアントとインターフェース変数に対する終了処理を実行します。
Clear public
TCanvas オブジェクトの表面のクリアします。
ClearRect public
TCanvas オブジェクトから、四角形の領域をクリアします。
Create public
DefaultHandler public
メッセージレコードを処理するメソッドのインターフェースを提供します。
Destroy public
現在の TCanvas とそのコンポーネントを破壊し、メモリも解放します。
Dispatch public
Message パラメータの内容に基づいてオブジェクトのメッセージ処理メソッドを呼び出します。
DrawArc public
TCanvas 上の楕円形の曲線の一部として、弧を描画します。
DrawBitmap public
TBitmap イメージから指定された領域を、イメージが TCanvas の指定された領域へスケーリングされた後に描画します。
DrawDashRect public
DrawEllipse public
四角形の境界線で定義される楕円を、現在の TCanvas 上に描画します。
DrawLine public
2 つの点で定義される線を、現在の TCanvas 上に描画します。
DrawPath public
path を、現在の TCanvas 上に描画します。
DrawPolygon public
多角形 を、現在の TCanvas 上に描画します。
DrawRect public
カスタマイズされた角のrectangleを、現在の TCanvas に描画します。
DrawRectSides public
カスタマイズされた角を持つrectangleの指定された辺を、現在の TCanvas に描画します。
EndScene public
描画完了したことを TCanvas オブジェクトに通知します。
Equals public
現在のインスタンスとパラメータが等しいかどうかを調べます。
ExcludeClipRect public
TCanvas のクリップ領域から四角形領域を除外します。
FieldAddress public
パブリッシュオブジェクト項目のアドレスを返します。
FillArc public
TCanvas 上の弧を塗りつぶします。
FillEllipse public
現在の TCanvas 上に、四角形の境界線で定義される楕円を塗りつぶして描画します。
FillPath public
現在の TCanvas 上に、パスを塗りつぶし、表示します。
FillPolygon public
現在の TCanvas 上に、多角形を塗りつぶし、表示します。
FillRect public
カスタマイズされた角の rectangle を塗りつぶし、現在の TCanvas に表示します。
FillText public
テキスト文字列を、現在の TCanvas の指定された四角形領域上に表示します。
FinalizeBitmap public
FlushBufferRect public
カラー データのビット ブロックを、指定されたデバイス コンテキストにコピーします。
Free public
オブジェクトを破棄し,必要ならば関連付けられているメモリを解放します。
FreeInstance public
NewInstance メソッドの前回の呼び出しによって割り当てられたメモリを解除します。
GetHashCode public
ハッシュ コードを表す整数を返します。
GetInterface public
指定したインターフェースを取り出します。
GetInterfaceEntry public
クラス内で実現された特定のインターフェースのエントリを返します。
GetInterfaceTable public
指定したクラスで実装されているすべてのインターフェースが入った構造体のポインタを返します。
GetNamePath public
オブジェクトインスペクタに表示されるオブジェクト名を返します。
InheritsFrom public
2 つのオブジェクト型の関係を調べます。
InitializeBitmap public
InitInstance public
新しく割り当てられたオブジェクトインスタンスをすべて 0 に初期化し,インスタンスの仮想メソッドテーブルポインタを初期化します。
InstanceSize public
オブジェクト型の各インスタンスのサイズをバイト数で返します。
IntersectClipRect public
TCanvas の現在のクリップ領域と四角形が、交差することにより描画領域を定義します。
LoadFontFromStream public
フォント ファミリをストリームからロードします。
MapBitmap public
MeasureLines public
指定された四角形に囲まれ、指定されたプロパティを持つ特定のテキストの、行を測定します。
MeasureText public
指定された揃え位置、フラグ、現在のフォントで表示される、テキスト文字列が TCanvas 上で占める領域を測ります。
MethodAddress public
名前を指定すると、クラス メソッドのアドレスを返します。
MethodName public
アドレスを指定すると、クラス メソッドの名前を返します。
MultiplyMatrix public
Matrix プロパティを拡大させます。
NewInstance public
オブジェクト型のインスタンスにメモリを割り当て,その新しいインスタンスを指すポインタを返します。
operator () public
PtInPath public
特定の頂点が、TPathData に属しているかどうかを確認します。
QualifiedClassName public
クラスの修飾名を返します。
QueryInterface public
指定されたインターフェースをオブジェクトがサポートしている場合,そのインターフェースへの参照を返します。
ResizeBuffer public
バッファをサイズ変更します。
RestoreState public
TCanvas の描画と設定済みのプロパティを、保存されている状態まで復元します。
SafeCallException public
safecall 呼び出し規約を使って宣言されたメソッド内での例外を処理します。
SaveState public
TCanvas の現在の描画と設定済みのプロパティを保存します。
SetCustomDash public
アウトラインのスタイルをカスタマイズします。
SetMatrix public
Matrix プロパティを設定します。
TextHeight public
現在の Font でレンダリングされるテキストの高さを、ピクセルで返します。
TextToPath public
揃え位置、現在のフォントが指定されたテキスト文字列から、TPathData を作成します。
TextWidth public
現在のフォント でレンダリングされるテキストの幅を、ピクセルで返します。
ToString public
クラス名を表す文字列を返します。
UnitName public
クラスが定義されているユニットの名前を返します。
UnitScope public クラスのユニット スコープを返します。
UnmapBitmap public |
VCLの Pixelsプロパティそのもの、というのは無いと思いますが、マップ(Map)を使えば多少ややこしいものの同様の操作は出来るのではないかと思います。
また、回転系では、Direct2D同様、Matrixを使う事になると思われます。
なお、速度的には、VCLアプリケーションで
procedure TForm1.Button1Click(Sender: TObject);
var
d : TDateTime ;
i : integer ;
begin
d := Now ;
with PaintBox1 do begin
for i:=1 to 100000 do begin
Canvas.Pen.Color := dword(i) ;
Canvas.MoveTo(0,i);
Canvas.LineTo(100000,i) ;
end;
end;
d := Now - d ;
ShowMessage('時間:'+FormatDateTime('hh:nn:ss.zzz',d));
end; |
というプログラムを作成して実行した結果は、この普通のノートパソコンの場合、340ミリ秒程度ですが、FireMonkeyアプリケーションで
procedure TForm1.Button1Click(Sender: TObject);
var
d : TDateTime ;
i : integer ;
begin
d := Now ;
with PaintBox1 do begin
Canvas.BeginScene ;
Canvas.Stroke.Kind := TBrushKind.bkSolid ;
for i:=1 to 100000 do begin
Canvas.Stroke.Color := $FF000000 + dword(i) ;
Canvas.DrawLine(PointF(0,i),PointF(100000,i),1.0) ;
end;
Canvas.EndScene ;
end;
d := Now - d ;
ShowMessage('時間:'+FormatDateTime('hh:nn:ss.zzz',d));
end; |
というプログラムを開発環境(IDE)から実行した場合の結果は、790ミリ秒程度と、約2倍の時間が掛かっています。しかし、DelphiXE3 プログラム開発環境を終了し、エクスプローラ等から、出来上がった実行型ファイルをダブルクリックして動作させた場合の結果は、300ミリ秒程度となります。つまり、少なくともこの件のプログラムに関しては、VCLアプリケーション以下の時間で実行する事が出来ます。勿論これは、CPUやGPUによって動作速度は変化する可能性も高いので一概には言えないのですが、それよりは、MacOS等でのアプリ開発可能性という意味で有効であると思われますし、また、高速CPU・GPUを利用すれば、より高速動作が可能かもしれない?という意味において、既に頭打ち状態の WindowsGDI描画よりは、多少なりとも、期待は持てる?かもしれません。
|
|
バッチファイル
BASIC
C言語のお勉強
拡張子な話
DOSプログラム
Delphi
>Delphi入門編
>Delphi2010
>DelphiXE3
▲2013/12/26
2013/12/27
▼2013/12/28
シェアウェア
Script!World
データベース
|