3つのボタンと1つの手続き

例えば、3つのボタンで1つのパネルの色を「白」→「青」→「赤」の順に表示させたいとします。つまり、どのボタンが押されてもパネルの色は、必ず「白」→「青」→「赤」の順に表示させるようにします。もし、パネルの色が「青」だった場合、どのボタンが押されても必ず次に表示される色は「赤」にしたいようにします。

どのようにすれば、この条件が実現できるでしょうか。パネルの色で条件分岐させることが出来そうです。これでやってみましょう。ボタン3つ、パネル( Panel )1つをフォームに貼り付けて下さい。(共に Standard ページにあります。)

procedure TForm1.Button1Click(Sender: TObject);
begin
  if Panel1.Color = clWhite then
    Panel1.Color := clBlue
  else if Panel1.Color = clBlue then
    Panel1.Color := clRed
  else
    Panel1.Color := clWhite;
end;
  
procedure TForm1.Button2Click(Sender: TObject);
begin
  if Panel1.Color = clWhite then
    Panel1.Color := clBlue
  else if Panel1.Color = clBlue then
    Panel1.Color := clRed
  else
    Panel1.Color := clWhite;
end;
  
procedure TForm1.Button3Click(Sender: TObject);
begin
  if Panel1.Color = clWhite then
    Panel1.Color := clBlue
  else if Panel1.Color = clBlue then
    Panel1.Color := clRed
  else
    Panel1.Color := clWhite;
end;

一応、期待する動作が出来ました。しかし、少し単調で見難い気もします。今度は if 文ではなく、case で場合分けをするとどうなるでしょうか。case でやるわけですから、パネルの色からは判断できません。例えば、一つの変数を用意して、その値をボタンをクリックするごとに値を変化させて、それでパネルの色を変化させるようにしてやるとどうなるでしょうか。やってみましょう。

  unit Unit1;
  
  interface
  
  uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, ExtCtrls, StdCtrls;
  
  type
    TForm1 = class(TForm)
      Button1: TButton;
      Button3: TButton;
      Button2: TButton;
      Panel1: TPanel;
      procedure Button1Click(Sender: TObject);
      procedure Button2Click(Sender: TObject);
      procedure Button3Click(Sender: TObject);
    private
      { Private 宣言 }
    public
      { Public 宣言 }
    end;
  
  var
    Form1: TForm1;
  
  implementation
  
  {$R *.dfm}
  
  var
    Global: Integer = 0; // グローバル変数
  
  procedure TForm1.Button1Click(Sender: TObject);
  begin
    case Global of
      0: Panel1.Color := clWhite;
      1: Panel1.Color := clBlue;
      2: Panel1.Color := clRed;
    end;
  
    Inc(Global);
    if Global = 3 then
      Global := 0;
  end;
  
  procedure TForm1.Button2Click(Sender: TObject);
  begin
    case Global of
      0: Panel1.Color := clWhite;
      1: Panel1.Color := clBlue;
      2: Panel1.Color := clRed;
    end;
  
    Inc(Global);
    if Global = 3 then
      Global := 0;
  end;
  
  procedure TForm1.Button3Click(Sender: TObject);
  begin
    case Global of
      0: Panel1.Color := clWhite;
      1: Panel1.Color := clBlue;
      2: Panel1.Color := clRed;
    end;
  
    Inc(Global);
    if Global = 3 then
      Global := 0;
  end;
  
  end.

少し見やすくなりました。ここでは、グローバル変数を使っています。こうすることによって、どの手続き( procedure )、又は関数( function )からも、この変数( Global )を使うことが出来ます。

case 文でも何とか期待通りの動作をさせることが出来ました。が、何だかこれも少し単調な気がします。上の2つ方法を良く見てみると、実はどの動作も同じことをやっています。それでは、共通の操作を一つの手続きにしてみてはどうでしょうか。 やってみましょう。

  unit Unit1;
  
  interface
  
  uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, ExtCtrls, StdCtrls;
  
  type
    TForm1 = class(TForm)
      Button1: TButton;
      Button3: TButton;
      Button2: TButton;
      Panel1: TPanel;
      procedure Button1Click(Sender: TObject);
      procedure Button2Click(Sender: TObject);
      procedure Button3Click(Sender: TObject);
    private
      { Private 宣言 }
    public
      { Public 宣言 }
      procedure ChangeColor; // 忘れないで下さい!
    end;
  
  var
    Form1: TForm1;
  
  implementation
  
  {$R *.dfm}
  
  var
    Global: Integer = 0; // グローバル変数
  
  procedure TForm1.ChangeColor;
  begin
    case Global of
      0: Panel1.Color := clWhite;
      1: Panel1.Color := clBlue;
      2: Panel1.Color := clRed;
    end;
  
    Inc(Global);
    if Global = 3 then
      Global := 0;
  end;
  
  
  procedure TForm1.Button1Click(Sender: TObject);
  begin
    ChangeColor;
  end;
  
  procedure TForm1.Button2Click(Sender: TObject);
  begin
    ChangeColor;
  end;
  
  procedure TForm1.Button3Click(Sender: TObject);
  begin
    ChangeColor;
  end;
  
  end.

前より大分すっきりしました。が、実はこんなことをするよりもっと良い方法が Delphi には用意されています。この3つのボタンの動作を1つの手続きにさせることが出来ちゃいます。

ここで、一旦全て終了させて下さい。そして、「ファイル」→「新規作成」→「アプリケーション」で新しくまたコンポーネントを再配置して下さい。まず最初にフォーム上で3つのボタンを選択します。下の図を参考にしてください。

次に、この状態のままでオブジェクトインスペクタへ移動して、以下のようにして下さい。

すると以下のようなコードが自動生成されます。

procedure TForm1.AllButtonClick(Sender: TObject);
begin
  
end;

ここに記述されたコードは、3つのボタンのどれを押されても実行されるようになります。それでは、以下のように書いてください。

var
  Global: Integer = 0;
  
procedure TForm1.AllButtonClick(Sender: TObject);
begin
  case Global of
    0: Panel1.Color := clWhite;
    1: Panel1.Color := clBlue;
    2: Panel1.Color := clRed;
  end;
  
  Inc(Global);
  if Global = 3 then
    Global := 0;
end;

このように、3つのボタンの動作を1つの手続きにすることが出来ます。これで、目標は達成できました。ここまで、来たので Tag の使い方もみてみましょう。 いろいろなコンポーネントには Tag プロパティがあります。この Tag プロパティは実際、何かが定義されているものではありません。プログラマが必要に応じて使うだけのものです。 今回の例では、3つのボタンが同じような動作をします。これは、言い換えると3つのボタンに区別がないとも言えます。このような場合、Tag プロパティに任意の整数値を与えてそれぞれを識別するように出来ます。

それでは、実際試して見ましょう。オブジェクトインスペクタでTagプロパティを変えます。
Button1 の Tag プロパティを 1
Button2 の Tag プロパティを 2
Button3 の Tag プロパティを 3 にして下さい。

ここでは、実際にどのボタンが押されたかをラベルに表示させて見たいと思います。それではラベルをフォームに貼り付けて、さっきのプログラムに以下のコードを付け加えて下さい。

var
  Global: Integer = 0;
  
procedure TForm1.AllButtonClick(Sender: TObject);
begin
  case Global of
    0: Panel1.Color := clWhite;
    1: Panel1.Color := clBlue;
    2: Panel1.Color := clRed;
  end;
  
  Inc(Global);
  if Global = 3 then
    Global := 0;
  
  case (Sender as TButton).Tag of
    1: Label1.Caption := 'Button1が押されました';
    2: Label1.Caption := 'Button2が押されました';
    3: Label1.Caption := 'Button3が押されました';
  end;
end;

Sender が気になると思います。これは、イベントが起こるコントロールを指しています。Sender については、これ以降でもっとよく見ていきますので、ここでは Tag についてだけ見て下さい。 このように Tag プロパティでどのボタンかを判断しています。

どのボタンが押されたのかを、ちゃんと判別することが出来ます。

今回、グローバル変数を使用しました。上のサンプルコードからも分かるように、グローバル変数は、あらかじめ初期化することが可能です。もし明示的に初期化をしなかった場合は、自動的に 0 に初期化されます。(string なら空文字、ポインタなら nil に初期化されます) ですから、今回の例のように 0 で初期化するなら、Global: Integer = 0; と書く必要はなく Global: Integer; だけで OK です。


up next
Last update 2002/3/3