Difference between revisions of "Developing with Graphics/ja"

From Lazarus wiki
Jump to navigationJump to search
 
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
{{Developing with Graphics}}
 +
 +
{{Japanese Menu}}
 +
 
このページは、どのようにビットマップや、その他のグラフィックスを扱うかのチュートリアルの最初のページになるでしょう。
 
このページは、どのようにビットマップや、その他のグラフィックスを扱うかのチュートリアルの最初のページになるでしょう。
 
私はグラフィクスに携わっていないので、専門的な経験を披露してくれる皆さんを招待します。
 
私はグラフィクスに携わっていないので、専門的な経験を披露してくれる皆さんを招待します。
Line 5: Line 9:
 
このページで、一般的なお知らせをすることがあります。
 
このページで、一般的なお知らせをすることがあります。
  
(訳注:すみません、Wikiでうまく「日本語」ページとしてリンクが出来ていません。どうすればいいのでしょうか。)
 
  
 +
__TOC__
 +
 +
==その他のグラフィックス==
 +
* [[GLScene/ja]] - OpenGL ライブラリの移植 [http://www.glscene.org GLScene]
 +
* [[TAChart/ja]] - Lazarus用のチャートコンポーネント
 +
* [[PascalMagick/ja]] - インターフェース用の簡単なAPI [http://www.imagemagick.org ImageMagick],マルチプラットホームでのビットマップを扱うフリーソフトウエア
 +
* [[PlotPanel/ja]] - アニメーショングラフのためのチャートや描画コンポーネント
 +
 +
==TBitmapの作業 ==
 +
 +
まず覚えていただきたいことは、Lazarusはプラットホームに対して独立しているということです。
 +
ですから、WindowsAPIの機能を使うメソッドは言うまでもなく、つかわないでください。
 +
たとえば、Scanlineのようなメソッドは、Lazarusではサポートしません。
 +
なぜなら、ScanlineはDevice Independant Bitmap(DIB)を扱い、結局GDI32.dllを使うことになるから(プラットホーム独立ではなくなるから)です。
 +
 +
[[doc:lcl/graphics/tbitmap.html|TBitmap]]にwidth,heightを特定しないなら、デフォルトはかなり小さいものになっているので、気をつけてください。
 +
 +
 +
===フェーディングの例===
 +
フェーディングするピクチャを作る場合、Delphiでは、このように書けます。
 +
 +
<code>
 +
type
 +
  PRGBTripleArray = ^TRGBTripleArray;
 +
  TRGBTripleArray = array[0..32767] of TRGBTriple;
 +
 +
procedure TForm1.FadeIn(aBitMap: TBitMap);
 +
var
 +
  Bitmap, BaseBitmap: TBitmap;
 +
  Row, BaseRow: PRGBTripleArray;
 +
  x, y, step: integer;
 +
begin
 +
  Bitmap := TBitmap.Create;
 +
  try
 +
    Bitmap.PixelFormat := pf32bit;  //  or pf24bit
 +
    Bitmap.Assign(aBitMap);
 +
    BaseBitmap := TBitmap.Create;
 +
    try
 +
      BaseBitmap.PixelFormat := pf32bit;
 +
      BaseBitmap.Assign(Bitmap);
 +
      for step := 0 to 32 do begin
 +
        for y := 0 to (Bitmap.Height - 1) do begin
 +
          BaseRow := BaseBitmap.Scanline[y];
 +
          Row := Bitmap.Scanline[y];
 +
          for x := 0 to (Bitmap.Width - 1) do begin
 +
            Row[x].rgbtRed := (step * BaseRow[x].rgbtRed) shr 5;
 +
            Row[x].rgbtGreen := (step * BaseRow[x].rgbtGreen) shr 5; // Fading
 +
            Row[x].rgbtBlue := (step * BaseRow[x].rgbtBlue) shr 5;
 +
          end;
 +
        end;
 +
        Form1.Canvas.Draw(0, 0, Bitmap);
 +
        InvalidateRect(Form1.Handle, nil, False);
 +
        RedrawWindow(Form1.Handle, nil, 0, RDW_UPDATENOW);
 +
      end;
 +
    finally
 +
      BaseBitmap.Free;
 +
    end;
 +
  finally
 +
    Bitmap.Free;
 +
  end;
 +
end;
 +
</code>
 +
 +
 +
上の関数は、Lazarusでは、このように実装します:
 +
 +
<code>
 +
procedure TForm1.FadeIn(ABitMap: TBitMap);
 +
var
 +
  SrcIntfImg, TempIntfImg: TLazIntfImage;
 +
  ImgHandle,ImgMaskHandle: HBitmap;
 +
  FadeStep: Integer;
 +
  px, py: Integer;
 +
  CurColor: TFPColor;
 +
  TempBitmap: TBitmap;
 +
begin
 +
  SrcIntfImg:=TLazIntfImage.Create(0,0);
 +
  SrcIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
 +
  TempIntfImg:=TLazIntfImage.Create(0,0);
 +
  TempIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
 +
  TempBitmap:=TBitmap.Create;
 +
  for FadeStep:=1 to 32 do begin
 +
    for py:=0 to SrcIntfImg.Height-1 do begin
 +
      for px:=0 to SrcIntfImg.Width-1 do begin
 +
        CurColor:=SrcIntfImg.Colors[px,py];
 +
        CurColor.Red:=(CurColor.Red*FadeStep) shr 5;
 +
        CurColor.Green:=(CurColor.Green*FadeStep) shr 5;
 +
        CurColor.Blue:=(CurColor.Blue*FadeStep) shr 5;
 +
        TempIntfImg.Colors[px,py]:=CurColor;
 +
      end;
 +
    end;
 +
    TempIntfImg.CreateBitmap(ImgHandle,ImgMaskHandle,false);
 +
    TempBitmap.Handle:=ImgHandle;
 +
    TempBitmap.MaskHandle:=ImgMaskHandle;
 +
    Canvas.Draw(0,0,TempBitmap);
 +
  end;
 +
  SrcIntfImg.Free;
 +
  TempIntfImg.Free;
 +
  TempBitmap.Free;
 +
end;
 +
</code>
 +
 +
このページのLazarusのコードは、 $LazarusPath/examples/lazintfimage/fadein1.lpi のプロジェクトから取ってきたものです。
 +
もし、あなたが画像処理プログラムで早いスタートをしたいなら、この例を良く読みましょう。
 +
 +
 +
===色(が)透明なビットマップを描く===
 +
 +
Lazarus 0.9.11で実装された新しい機能で、色透明ビットマップを描画することができます。
 +
ビットマップファイル(*.BMP)は、透明性のどんな情報を持つことができません。しかし、ビットマップ上のある色を透明色と選択すれば、色透明ビットマップにすることができます。これは、Win32アプリケーションでよくつかわれてきたトリックです。
 +
 +
次のサンプルはWindowsのリソースからビットマップをロードし、透明となる色(clFuchsia)を指定し、canvasに描画します。
 +
 +
<pre>
 +
procedure MyForm.MyButtonOnClick(Sender: TObject);
 +
var
 +
  buffer: THandle;
 +
  bmp: TBitmap;
 +
  memstream: TMemoryStream;
 +
begin
 +
  bmp := TBitmap.Create;
 +
 +
  buffer := Windows.LoadBitmap(hInstance, MAKEINTRESOURCE(ResourceID));
 +
 +
  if (buffer = 0) then exit; // Error loading the bitmap
 +
 +
  bmp.Handle := buffer;
 +
  memstream := TMemoryStream.create;
 +
  try
 +
    bmp.SaveToStream(memstream);
 +
    memstream.position := 0;
 +
    bmp.LoadFromStream(memstream);
 +
  finally
 +
    memstream.free;
 +
  end;
 +
 +
  bmp.Transparent := True;
 +
  bmp.TransparentColor := clFuchsia;
 +
 +
  MyCanvas.Draw(0, 0, bmp);
 +
 +
  bmp.Free; // Release allocated resource
 +
end;
 +
</pre>
 +
 +
[[doc:rtl/classes/tmemorystream.html|TMemoryStream]]でメモリ操作を行っていることに注意してください。
 +
それらは、読み込んだイメージを確実に操作するのに必要です。
 +
 +
 +
 +
== 動きのあるグラフィックス - チラツキを防止する方法 ==
 +
 +
多くのプログラムが、2D画像としてGUIを描画します。
 +
それらの画像は、高速に変更する必要がある場合、すぐ次のような問題に直面します。高速に更新する画像は、しばしばスクリーン上でチラツキをおこします。
 +
時々、全体的なイメージをユーザーが見ている時、ほんの一部分だけ描画される時、発生します。
 +
それは、描画の作業に時間がかかるのでおこります。
 +
 +
しかし、どのようにしたらチラツキを防止し、最善の描画速度を得ることができるのでしょうか。もちろん、OpenGLを使ったハードウエアアクセラレーションを使うこともできます。しかし、この方法は小さなプログラムや古いコンピュータには、大変重いものです。
 +
このチュートリアルでは、TCanvasに描画する方法に焦点をしぼります。
 +
もし、OpenGLの助けが必要であれば、Lazarusについてくるサンプルを見てください。ほかにも、ダブルバッファをサポートしたcanvasや、スプライトコンポーネントのあるA.J.Venterのgamepackを使うこともできます。
  
(英文による 原文)
+
それでは、Canvasに描画するオプションを調べてみましょう。
This page will be the start of tutorials with regard to manipulating Bitmaps and other graphics. As I am not a graphics programmer, I invite all who are to share their expertise! Just add a link to the next section, add a page and create your own WiKi article.
 
  
On this page some general information will be given.
+
* [[#Draw to a TImage|Draw to a TImage]]
 +
* [[#Draw on the OnPaint event|Draw on the OnPaint event of the form, a TPaintBox or another control]]
 +
* [[#Create a custom control which draws itself|Create a custom control which draws itself]]
 +
* [[#Using A.J. Venter's gamepack|Using A.J. Venter's gamepack]]
  
  
  
ビットマップ上の作業  (訳注:本来は別セクションとして記述)
+
===TImageに描画する===
Working with TBitmap
 
  
 +
TImageに描画するのにOnPaintイベントを使ってはいけません。
 +
TImageはバッファされていますので、あなたが一度描画したり変更しさえすれば、TImageはずっとそのイメージを持続します。
 +
しかし、コンスタントに再描画をおこなえば、チラツキが発生するでしょう。
 +
この場合に、他の方法を試します。
 +
TImageに描画することは、ほかの方法よりも遅いのです。
  
最初に思い出してほしいのは、Lazarusはプラットホームに対して独立しているということです。
+
<code>
ですから、WindowsAPIの機能を使うメソッドは言うまでもありません。
+
procedure TForm1.BitBtn1Click(Sender: TObject);
Scanlineを使うメソッドは、Lazarusではサポートしません。
+
var
なぜなら、ScanlineはDevice Independant Bitmap(DIB)を扱い、GDI32.dllを使うことになるからです。
+
  x, y: Integer;
 +
begin
 +
  // Draws the backgroung
 +
  MyImage.Canvas.Pen.Color := clWhite;
 +
  MyImage.Canvas.Rectangle(0, 0, Image.Width, Image.Height);
 +
 
 +
  // Draws squares
 +
  MyImage.Canvas.Pen.Color := clBlack;
 +
  for x := 1 to 8 do
 +
    for y := 1 to 8 do
 +
    MyImage.Canvas.Rectangle(Round((x - 1) * Image.Width / 8), Round((y - 1) * Image.Height / 8),
 +
        Round(x * Image.Width / 8), Round(y * Image.Height / 8));
 +
end;
 +
</code>
  
もし、あなたがTBitmapにwidth,heightを特定しないなら、デフォルトはかなり小さいものになっているので、気をつけてください。
+
===OnPaintイベントで描画する===
  
フェーディングの例:
+
この場合、フォームのOnPaintイベントで、すべての描画が終了しなければなりません。この方法ではTImageのように、バッファには残りません。
フェーディングするピクチャを作りたい場合、Delphiでは、このように書けます。
 
  
 +
===自分自身を描画するカスタムコントロールを作成する===
  
 +
カスタムコントロールを作成することは、あなたのコードを構造化し、そのコントロールを再利用できる、という利点があります。
 +
この方法はとても高速ですが、まず、TBitmapに描画して、canvasにそれを転送しなければ、チラツキを発生することがあります。この方法では、コントロールのOnPaintイベントを必要としません。
  
(英文による 原文)
+
カスタムコントロールの例:
The first thing to remember is that Lazarus is meant to be platform independent, so any methods using Windows API functionality are out of the question. So a method like ScanLine is not supported by Lazarus because it is intended for Device Independant Bitmap and uses functions from the GDI32.dll.
 
  
Be careful that if you do not specify the width and height of your TBitmap it will have the standard one, which is quite small.  
+
<code>
 +
type
 +
  TMyDrawingControl = class(TCustomControl)
 +
  public
 +
    procedure Paint; override;
 +
  end;
 +
 +
implementation
 +
 +
procedure TMyDrawingControl.Paint;
 +
var
 +
  x, y: Integer;
 +
  Bitmap: TBitmap;
 +
begin
 +
  Bitmap := TBitmap.Create;
 +
  try
 +
    // Initializes the Bitmap Size
 +
    Bitmap.Height := Height;
 +
    Bitmap.Width := Width;
 +
 
 +
    // Draws the background
 +
    Bitmap.Canvas.Pen.Color := clWhite;
 +
    Bitmap.Canvas.Rectangle(0, 0, Width, Height);
 +
 +
    // Draws squares
 +
    Bitmap.Canvas.Pen.Color := clBlack;
 +
    for x := 1 to 8 do
 +
      for y := 1 to 8 do
 +
      Bitmap.Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8),
 +
        Round(x * Width / 8), Round(y * Height / 8));
 +
     
 +
    Canvas.Draw(0, 0, Bitmap);
 +
  finally
 +
    Bitmap.Free;
 +
  end;
 +
 +
  inherited Paint;
 +
end;
 +
</code>
  
[edit]A fading example
+
フォーム上で生成する方法は次のとおりです:
Say you want to make a Fading picture. In Delphi you could do something like:  
+
<code>
 +
procedure TMyForm.FormCreate(Sender: TObject);
 +
begin
 +
  MyDrawingControl:= TMyDrawingControl.Create(Self);
 +
  MyDrawingControl.Height := 400;
 +
  MyDrawingControl.Width := 500;
 +
  MyDrawingControl.Top := 0;
 +
  MyDrawingControl.Left := 0;
 +
  MyDrawingControl.Parent := Self;
 +
  MyDrawingControl.DoubleBuffered := True;
 +
end;
 +
</code>
  
<< コード例
+
destroyを忘れてはいけない。
 +
(訳注: CreateでFormのSelfを指定しているから、いらないのでは?)
 +
just don´t forget to destroy it:
 +
<code>
 +
procedure TMyForm.FormDestroy(Sender: TObject);
 +
begin
 +
  MyDrawingControl.Free;
 +
end;
 +
</code>
  
 +
TopとLeftは、0が標準の位置なので、かならずしも設定する必要はありません。
 +
しかし、これは、コントロールが置かれる位置を再設定します。
  
上の関数は、Lazarusでは、このように実装します。
+
"MyDrawingControl.Parent := Self;"は、とても重要です。これを書かなくては、コントロールが表示されません。
  
(英文による 原文)
+
"MyDrawingControl.DoubleBuffered := True;" は、Windows上でチラツキを防止するためのものです。gtk上では何の効果もありません。
This function in Lazarus could be implemented like:
+
(訳注:gtk上では、効果がないのか、そもそも、DoubleBufferdを指定する必要がないのか?どっちだろう。)
  
(英文による 原文)
+
===A.J.Venterのgamepackを使う===
  
Notice the memory operations performed with the TMemoryStream. They are necessary to ensure the correct loading of the image.  
+
gamepackによる方法は、すべてのものを、1つのダブルバッファされたcanvasに描画してしまおう、というものです。あなたが更新を準備できた時点で、、見えるcanvasの変更をおこなうことができます。多少コードを必要としますが、多くのスプライトをもつ"シーン"を、大幅に高速に描画更新できる、という利点があります。もし、このアプローチを使いたくなったら、Lazarusのゲーム開発コンポーネントセットであるA.J.Venterのgamepackに興味をもったでしょう。gamepackは、スプライト同様にダブルバッファを表示するエリアを提供してくれますし、ひとつひとつが、大変上手く統合されています。
 +
gamepackはsubversionを通して得ることができます。<br />
 +
<code>
 +
svn co svn://silentcoder.co.za/lazarus/gamepack
 +
</code>
  
  
<< コード例
+
<code>
 +
svn co svn://silentcoder.co.za/lazarus/gamepack
 +
</code>

Latest revision as of 13:24, 31 March 2008

Deutsch (de) English (en) español (es) français (fr) italiano (it) 日本語 (ja) 한국어 (ko) Nederlands (nl) português (pt) русский (ru) slovenčina (sk) 中文(中国大陆)‎ (zh_CN) 中文(台灣)‎ (zh_TW)

日本語版メニュー
メインページ - Lazarus Documentation日本語版 - 翻訳ノート - 日本語障害情報

このページは、どのようにビットマップや、その他のグラフィックスを扱うかのチュートリアルの最初のページになるでしょう。 私はグラフィクスに携わっていないので、専門的な経験を披露してくれる皆さんを招待します。 次の項目にリンクやページを追加して、Wikiを製作してください。

このページで、一般的なお知らせをすることがあります。


その他のグラフィックス

  • GLScene/ja - OpenGL ライブラリの移植 GLScene
  • TAChart/ja - Lazarus用のチャートコンポーネント
  • PascalMagick/ja - インターフェース用の簡単なAPI ImageMagick,マルチプラットホームでのビットマップを扱うフリーソフトウエア
  • PlotPanel/ja - アニメーショングラフのためのチャートや描画コンポーネント

TBitmapの作業

まず覚えていただきたいことは、Lazarusはプラットホームに対して独立しているということです。 ですから、WindowsAPIの機能を使うメソッドは言うまでもなく、つかわないでください。 たとえば、Scanlineのようなメソッドは、Lazarusではサポートしません。 なぜなら、ScanlineはDevice Independant Bitmap(DIB)を扱い、結局GDI32.dllを使うことになるから(プラットホーム独立ではなくなるから)です。

TBitmapにwidth,heightを特定しないなら、デフォルトはかなり小さいものになっているので、気をつけてください。


フェーディングの例

フェーディングするピクチャを作る場合、Delphiでは、このように書けます。

type
  PRGBTripleArray = ^TRGBTripleArray;
  TRGBTripleArray = array[0..32767] of TRGBTriple;

procedure TForm1.FadeIn(aBitMap: TBitMap);
var
  Bitmap, BaseBitmap: TBitmap;
  Row, BaseRow: PRGBTripleArray;
  x, y, step: integer;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.PixelFormat := pf32bit;  //  or pf24bit
    Bitmap.Assign(aBitMap);
    BaseBitmap := TBitmap.Create;
    try
      BaseBitmap.PixelFormat := pf32bit;
      BaseBitmap.Assign(Bitmap);
      for step := 0 to 32 do begin
        for y := 0 to (Bitmap.Height - 1) do begin
          BaseRow := BaseBitmap.Scanline[y];
          Row := Bitmap.Scanline[y];
          for x := 0 to (Bitmap.Width - 1) do begin
            Row[x].rgbtRed := (step * BaseRow[x].rgbtRed) shr 5;
            Row[x].rgbtGreen := (step * BaseRow[x].rgbtGreen) shr 5; // Fading
            Row[x].rgbtBlue := (step * BaseRow[x].rgbtBlue) shr 5;
          end;
        end;
        Form1.Canvas.Draw(0, 0, Bitmap);
        InvalidateRect(Form1.Handle, nil, False);
        RedrawWindow(Form1.Handle, nil, 0, RDW_UPDATENOW);
      end;
    finally
      BaseBitmap.Free;
    end;
  finally
    Bitmap.Free;
  end;
end;


上の関数は、Lazarusでは、このように実装します:

procedure TForm1.FadeIn(ABitMap: TBitMap);
var
  SrcIntfImg, TempIntfImg: TLazIntfImage;
  ImgHandle,ImgMaskHandle: HBitmap;
  FadeStep: Integer;
  px, py: Integer;
  CurColor: TFPColor;
  TempBitmap: TBitmap;
begin
  SrcIntfImg:=TLazIntfImage.Create(0,0);
  SrcIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
  TempIntfImg:=TLazIntfImage.Create(0,0);
  TempIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
  TempBitmap:=TBitmap.Create;
  for FadeStep:=1 to 32 do begin
    for py:=0 to SrcIntfImg.Height-1 do begin
      for px:=0 to SrcIntfImg.Width-1 do begin
        CurColor:=SrcIntfImg.Colors[px,py];
        CurColor.Red:=(CurColor.Red*FadeStep) shr 5;
        CurColor.Green:=(CurColor.Green*FadeStep) shr 5;
        CurColor.Blue:=(CurColor.Blue*FadeStep) shr 5;
        TempIntfImg.Colors[px,py]:=CurColor;
      end;
    end;
    TempIntfImg.CreateBitmap(ImgHandle,ImgMaskHandle,false);
    TempBitmap.Handle:=ImgHandle;
    TempBitmap.MaskHandle:=ImgMaskHandle;
    Canvas.Draw(0,0,TempBitmap);
  end;
  SrcIntfImg.Free;
  TempIntfImg.Free;
  TempBitmap.Free;
end;

このページのLazarusのコードは、 $LazarusPath/examples/lazintfimage/fadein1.lpi のプロジェクトから取ってきたものです。 もし、あなたが画像処理プログラムで早いスタートをしたいなら、この例を良く読みましょう。


色(が)透明なビットマップを描く

Lazarus 0.9.11で実装された新しい機能で、色透明ビットマップを描画することができます。 ビットマップファイル(*.BMP)は、透明性のどんな情報を持つことができません。しかし、ビットマップ上のある色を透明色と選択すれば、色透明ビットマップにすることができます。これは、Win32アプリケーションでよくつかわれてきたトリックです。

次のサンプルはWindowsのリソースからビットマップをロードし、透明となる色(clFuchsia)を指定し、canvasに描画します。

procedure MyForm.MyButtonOnClick(Sender: TObject);
var
  buffer: THandle;
  bmp: TBitmap;
  memstream: TMemoryStream;
begin
  bmp := TBitmap.Create;

  buffer := Windows.LoadBitmap(hInstance, MAKEINTRESOURCE(ResourceID));

  if (buffer = 0) then exit; // Error loading the bitmap

  bmp.Handle := buffer;
  memstream := TMemoryStream.create;
  try
    bmp.SaveToStream(memstream);
    memstream.position := 0;
    bmp.LoadFromStream(memstream);
  finally
    memstream.free;
  end;

  bmp.Transparent := True;
  bmp.TransparentColor := clFuchsia;

  MyCanvas.Draw(0, 0, bmp);

  bmp.Free; // Release allocated resource
end;

TMemoryStreamでメモリ操作を行っていることに注意してください。 それらは、読み込んだイメージを確実に操作するのに必要です。


動きのあるグラフィックス - チラツキを防止する方法

多くのプログラムが、2D画像としてGUIを描画します。 それらの画像は、高速に変更する必要がある場合、すぐ次のような問題に直面します。高速に更新する画像は、しばしばスクリーン上でチラツキをおこします。 時々、全体的なイメージをユーザーが見ている時、ほんの一部分だけ描画される時、発生します。 それは、描画の作業に時間がかかるのでおこります。

しかし、どのようにしたらチラツキを防止し、最善の描画速度を得ることができるのでしょうか。もちろん、OpenGLを使ったハードウエアアクセラレーションを使うこともできます。しかし、この方法は小さなプログラムや古いコンピュータには、大変重いものです。 このチュートリアルでは、TCanvasに描画する方法に焦点をしぼります。 もし、OpenGLの助けが必要であれば、Lazarusについてくるサンプルを見てください。ほかにも、ダブルバッファをサポートしたcanvasや、スプライトコンポーネントのあるA.J.Venterのgamepackを使うこともできます。

それでは、Canvasに描画するオプションを調べてみましょう。


TImageに描画する

TImageに描画するのにOnPaintイベントを使ってはいけません。 TImageはバッファされていますので、あなたが一度描画したり変更しさえすれば、TImageはずっとそのイメージを持続します。 しかし、コンスタントに再描画をおこなえば、チラツキが発生するでしょう。 この場合に、他の方法を試します。 TImageに描画することは、ほかの方法よりも遅いのです。

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  x, y: Integer;
begin
  // Draws the backgroung
  MyImage.Canvas.Pen.Color := clWhite;
  MyImage.Canvas.Rectangle(0, 0, Image.Width, Image.Height);
  
  // Draws squares
  MyImage.Canvas.Pen.Color := clBlack;
  for x := 1 to 8 do
   for y := 1 to 8 do
    MyImage.Canvas.Rectangle(Round((x - 1) * Image.Width / 8), Round((y - 1) * Image.Height / 8),
       Round(x * Image.Width / 8), Round(y * Image.Height / 8));
end;

OnPaintイベントで描画する

この場合、フォームのOnPaintイベントで、すべての描画が終了しなければなりません。この方法ではTImageのように、バッファには残りません。

自分自身を描画するカスタムコントロールを作成する

カスタムコントロールを作成することは、あなたのコードを構造化し、そのコントロールを再利用できる、という利点があります。 この方法はとても高速ですが、まず、TBitmapに描画して、canvasにそれを転送しなければ、チラツキを発生することがあります。この方法では、コントロールのOnPaintイベントを必要としません。

カスタムコントロールの例:

type
  TMyDrawingControl = class(TCustomControl)
  public
    procedure Paint; override;
  end;

implementation

procedure TMyDrawingControl.Paint;
var
  x, y: Integer;
  Bitmap: TBitmap;
begin
  Bitmap := TBitmap.Create;
  try
    // Initializes the Bitmap Size
    Bitmap.Height := Height;
    Bitmap.Width := Width;
 
    // Draws the background
    Bitmap.Canvas.Pen.Color := clWhite;
    Bitmap.Canvas.Rectangle(0, 0, Width, Height);

    // Draws squares
    Bitmap.Canvas.Pen.Color := clBlack;
    for x := 1 to 8 do
     for y := 1 to 8 do
      Bitmap.Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8),
       Round(x * Width / 8), Round(y * Height / 8));
      
    Canvas.Draw(0, 0, Bitmap);
  finally
    Bitmap.Free;
  end;

  inherited Paint;
end;

フォーム上で生成する方法は次のとおりです:

procedure TMyForm.FormCreate(Sender: TObject);
begin
  MyDrawingControl:= TMyDrawingControl.Create(Self);
  MyDrawingControl.Height := 400;
  MyDrawingControl.Width := 500;
  MyDrawingControl.Top := 0;
  MyDrawingControl.Left := 0;
  MyDrawingControl.Parent := Self;
  MyDrawingControl.DoubleBuffered := True;
end;

destroyを忘れてはいけない。 (訳注: CreateでFormのSelfを指定しているから、いらないのでは?) just don´t forget to destroy it:

procedure TMyForm.FormDestroy(Sender: TObject);
begin
  MyDrawingControl.Free;
end;

TopとLeftは、0が標準の位置なので、かならずしも設定する必要はありません。 しかし、これは、コントロールが置かれる位置を再設定します。

"MyDrawingControl.Parent := Self;"は、とても重要です。これを書かなくては、コントロールが表示されません。

"MyDrawingControl.DoubleBuffered := True;" は、Windows上でチラツキを防止するためのものです。gtk上では何の効果もありません。 (訳注:gtk上では、効果がないのか、そもそも、DoubleBufferdを指定する必要がないのか?どっちだろう。)

A.J.Venterのgamepackを使う

gamepackによる方法は、すべてのものを、1つのダブルバッファされたcanvasに描画してしまおう、というものです。あなたが更新を準備できた時点で、、見えるcanvasの変更をおこなうことができます。多少コードを必要としますが、多くのスプライトをもつ"シーン"を、大幅に高速に描画更新できる、という利点があります。もし、このアプローチを使いたくなったら、Lazarusのゲーム開発コンポーネントセットであるA.J.Venterのgamepackに興味をもったでしょう。gamepackは、スプライト同様にダブルバッファを表示するエリアを提供してくれますし、ひとつひとつが、大変上手く統合されています。 gamepackはsubversionを通して得ることができます。
svn co svn://silentcoder.co.za/lazarus/gamepack


svn co svn://silentcoder.co.za/lazarus/gamepack