Sign in Join
Wiki copytemporary

Form Tutorial/ja

Deutsch · English · Suomi · 中文(中国) · 日本語

Lazarusでフォームを用いるための短いイントロダクション。

フォームとは何か

フォーム (class TForm)はapplicationのユーザーインターフェースとなるウインドウもしくはダイアログを表す。それは他のcomponents(例えば、ボタン、ラベル、編集ボックス、画像など)が挿入されるコンテナである。

初めてのGUIアプリケーション

Lazarusのインストールが成功し、新しいアプリケーションプロジェクトを始めると、空のフォームが作られる。そうでなければ、新しい GUI アプリケーションを メインメニュー -> プロジェクト -> 新規プロジェクト -> アプリケーション OKで作ることができる。

今、新しい、全機能が使えるフォームを持つプロジェクトが生成された:

新しく作られたプロジェクトを実行するには、単にF9キーを押す、もしくはマウスでメインメニューアイコン(あるいは メインメニュー: 実行 -> 実行)をクリックする。プロジェクトはコンパイル、実行される。

特に面白いことが起こるわけではない。フォーム(Form1)はわずかに外見が変わり、ラスタグリッドの点々(個々のコンポーネントの位置付けの助けとなる)が消える(グリッドの点が見えてる間は、それがデザインモードにあることがわかる):
->

次にフォームの上にTButtonを配することができる。これは後に第2のフォームを開くことを可能にするために使われる:

コンポーネントパレット上のStandardタブからTButtonを選ぶ。

そしてフォームをクリックする: 「Button1」の名前とキャプションでForm1にボタンが配される。

このボタンに何かをさせるために、それをクリックすると、何か意図したことをするようにボタンに告げなければならない。これは単純なイベントである。このためクリックされた後に呼ばれる イベントハンドラが必要である。マウスに対するイベントハンドラはボタンはButton1をダブルクリックすることにより、極めて簡単に行える(もしくはオブジェクトインスペクタで、Button1 -> イベントタブ -> OnClick、次いで[...]をクリック)。これはButton1がクリックされると(設計段階ではなくruntime)にいつも呼ばれるプロシージャTForm1.Button1Clickをコードエディタに作り出す。

アプリケーションにButton1をクリックした後に何かをさせるために、プロシージャTForm1.Button1ClickのBeginとEndの間にこのようにコードを加える:

pascal
procedure TForm1.Button1Click(Sender: TObject);
begin
  Caption:='My first Form';  //Form1のキャプションが変更される(フォーム冒頭のテキスト)
  //or
  Button1.Caption:='Hello';  //ボタンのキャプションが変更される(ボタンのテキストが表示される)
end;

そして、F9を押し、フォームを起動させる、ボタンをクリックしたときにフォームキャプションとボタンキャプションの双方が変わることに注意すること。

ちょっとした実験を行い、スタンダードコンポーネントの使い方を学んだ。始めるにあたり、以下のコンポーネントの例を試してみることを勧める:

TButton
TLabel
TEdit
TMemo
TToggleBox
TCheckBox
TRadioButton
TListBox
TComboBox
TScrollBar

ここにさらに役に立つ情報があるLazarusチュートリアル。

2つ目のフォームを使う

このチュートリアルでは1つのプロジェクトで複数のフォームを使う方法を示す。この例で2つだけのフォーム、Form1(メインフォーム)とForm2が作られるが、追加のフォームについてもその仕方は同一である。

クリックされると新しいフォームを開くボタンがメインフォームにある。新しいフォームはまた、クリックされるとそれ自身を閉じ、メインフォームに帰ってくるボタンを有する。 もし最初のチュートリアル、 初めてのGUIアプリケーションを終えているのなら、TForm1.Button1Clickプロシージャのbeginとendの間のコードを削除しておく必要がある。そうしないと、新たなプロジェクト(アプリケーション)フォームにボタンを置き、キャプション(ボタンの上の表示されるテキスト)を入力し、OnClickイベントハンドラをこのButton1に作らなければならない。
これを行うためボタンを選択(一度クリックする)し、オブジェクトインスペクタで、プロパティ -> Caption、「Open Form2」と入力する。

2つ目のフォーム(Form2)をプロジェクトに加えるため、メインメニューで ファイル -> 新規フォームを実行する。Form2にボタンを置きそれにOnClickイベントを作る。このボタンのキャプションを「Close」に変更する。

いま、このプロジェクトは2つのフォームを持ち、それぞれはメインメニュー、プロジェクト -> フォーム...(もしくはキーの組み合わせShift + F12)で選択、表示できる。また別に、ソースエディタでUnitタブで選択もでき、F12でコードエディタとUnitに割り当てられたフォームデザイナとを切り替えできる。

source code editorでUnit (Unit1)が割り当てられたForm1に行きUsesに節「Unit2を加える:

pascal
uses
  Classes, SysUtils, ... , Unit2;  // それぞれのユニットがコンマ(,)で区切られていることと
                                   // uses 節がセミコロン(;)で終わることは重要である。

今、Unit2(即ちForm2)をUnit1から呼び出すことができる。

次に、Form1に属するボタンのOnClickイベントを編集する:

pascal
unit Unit1;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.ShowModal;  //Form2を表示、フォーカスはForm2に来る。
end;
pascal
unit Unit2;
...
procedure TForm2.Button1Click(Sender: TObject);
begin
  Close;  //Form2を閉じる
end;

これで、プロジェクトを起動( もしくは F9)し、Form1のボタンをクリックすることでForm2を開くことができる。

ShowとShowModalの違い

Showおよび ShowModalメソッドは双方ともフォームを見えるようにする。ShowとShowModalの違いを見るために:

pascal
procedure TForm1.btnShowClick(Sender: TObject);
begin
  Form2.Show;
  ShowMessage('Form2 is opened!');
end;

procedure TForm1.btnShowModalClick(Sender: TObject);
begin
  Form2.ShowModal;
  ShowMessage('Form2 is opened and closed again!');
end;

Show

このプロシージャはフォームを見える状態にし、呼んだコントロール(Form1)のコードの実行を継続する。この例ではメッセージ、(ShowMessage) はほとんどForm2と同時に現れる。またForm1を呼んで使い続けることができる。例えばそれを動かしたり、Showボタンを押すことができる(しかしShowModalをクリックするとエラーが発生するだろう)。

<myForm>.Show;を用いる代わりに、<myForm>.Visible:=True;を用いることもできる、Showメソッドは以下を行う:

pascal
procedure TCustomForm.Show;
begin
  Visible := True;
  BringToFront;
end;

<myForm>.Show;と<myForm>.Visible:=True;の唯一の違いは、Showを用いてフォームを表示すると、現在表示されているすべての他のフォームの上に表示されることである。

ShowModal

ShowModalは新しく開かれているフォーム(Form2)が閉じられるまで呼び出したコントロール(Form1)を停止させる。例では、ShowModalの直後のShowMessage行はForm2が閉じた後にのみ実行される。フォームの呼び出しは固まってしまう;Form1を動かすこともそれが持つどのボタンも押すことができない。

ShowModalは整数値の結果を返す関数である。TModalResultを参照のこと。返された値によりどのようにフォームを閉じたかを分岐できる。

お互いを呼び出すことのできる2つのフォーム

2番目のフォームからメインフォームを呼ぶことを避けるのは一般的に良いプログラム設計である。2番目のフォームを閉じることによって、(前の例のように)メインフォームへ戻り、メインフォームにフォーカスを返すこともより好ましい。しかしこの例が示すように、サブフォームからメインフォームを呼ぶことは可能である。

Form1がForm2を呼ぶために、Unit1はそのUses節の中にUnit2を持っていなければならない。 逆にForm2がForm1を呼ぶために、Unit2はそのUses節にUnit1を持っていなければならない。これはお互いのユニットが他のユニットを参照しあう、潜在的な循環ユニット参照コンパイラエラーにつながる。この例は循環ユニット参照エラーをどのように避けるかも示している。

この例を設定するために、前の例(2つ目のフォームを使う)のフォームを改造する、、もしくはそれぞれが1個のボタンを持つ新しいプロジェクトを作る。Form1.Button1のキャプションを「Open Form2」、Form2.Button1のキャプションを「Open Form1」と設定する。

もし、前の例を改造するなら、Unit1のUses節から「Unit2」を除くこと。

それぞれのUnitのImplementationセクションにUses節を加える。Unit1の節にUnit2を、Unit2の節にUnit1を加えると以下のようになる:

pascal
unit Unit1;
...
implementation

uses
  Unit2;  
...
pascal
unit Unit2;
...
implementation

uses
  Unit1;  
...

ボタンイベントハンドラのOnClickイベント以後にあるコードを変更する:

pascal
unit Unit1;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show;  
end;
pascal
unit Unit2;
...
procedure TForm2.Button1Click(Sender: TObject);
begin
  Form1.Show; 
end;

他のフォームに変数を渡す

上記の例、2つ目のフォームを使うによれば、Unit2のinterface部でグローバル変数を宣言することができる。これはUnit1とUnit2の双方が同じ変数にアクセスすることを可能にする(Unit1のUses節にUnit2を置くことにより、Unit2のinterface部で宣言されたすべての変数も、Unit1で利用できるようになる)。この習慣は、どの個々の変数がスコープにあるかを記憶することが急速に困難となり、潜在的なエラーの元となるので、最小限にすべきである。ローカル変数を使い、Classの中のプロパティを、あるいは別にクラスの中の変数として定義することがより好ましい。

次のプロジェクトでは、2番目のフォームをボタンのクリックで開く。この時、メインフォームのユニットが2番目のフォームが何回表示されたかを勘定する。この2番目のフォームでボタンをクリックすることで、何回それが開かれたを見るために尋ねることができる:

pascal
unit Unit2;
...
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { プライベート宣言 }
  public
    { パブリック宣言 }
    const Count: Integer = 0;   //ここ
  end;
pascal
unit Unit1;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  inc(Form2.Count);  //Form2が呼ばれるたびにカウンタを1つ増やす
  Form2.ShowModal;   
end;
pascal
unit Unit2;
...
procedure TForm2.Button1Click(Sender: TObject);
begin
  ShowMessage('Form2 would be displayed '+IntToStr(Count)+' times');
end;

このようにUnit1の中でUnit2のすべてのパブリック変数/プロパティ/関数/プロシージャ(一般的なメソッド)にアクセスできる。

他のフォームに関する事柄

もう1つのフォームをメインフォームとして使う

もし起動時にしばらく異なるフォームもしくは視覚的に新しいフォームを表示させたいと決めたとすると、メインメニュー、プロジェクト -> プロフェクトオプション -> フォーム...を実行できる:

また別に、メインメニュー、プロフェクト -> 表示(Lazarus 3.2ではここに表示 - Showというメニューはない) .lprファイル、Project.lpr(メインプログラムのPascalコード)から、最初に表示されるフォームを作ることができる:

pascal
program Project1;
...
  Application.CreateForm(TForm2, Form2);  //Form2が最初に作られ、アプリケーションが起動されるときに表示される
  Application.CreateForm(TForm1, Form1);

プログラムの終わりで形のプロパティを保存する

動的にフォームを作る

Lazarusによってデザインされたフォームを動的に作る

アプリケーション起動中に呼び出されるかもしれないすべてのフォームを作る必要はない。開発者によっては一般的にそれを保持せずにProject.lprから、プロジェクトに新しくフォームを挿入するときに自動的に生成されたコードを削除する。もし、いくつかのGUIを含むライブラリを書きたいとすると、フォームの動的生成を避けては通れない。

例:

pascal
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2:=TForm2.Create(Nil);  //Form2が生成される
  Form2.ShowModal;            //Form2が表示される
  FreeAndNil(Form2);          //Form2解放
end;

新しいフォームを動的に生成する

以下はフォームデザイナを使わずにコードで新しいフォームを生成する例を示している。

この例ではボタンをクリックすることで、自身にボタンを含むもう1つのフォームが開くはずである。この2番目のボタンをクリックするとフォームを閉じると警告が出て、フォームが閉じられる。

pascal
procedure TForm1.Button1Click(Sender: TObject);
var
  MyForm: TForm;
  MyButton: TButton;
begin
  MyForm:=TForm.Create(nil);             
  MyForm.SetBounds(100, 100, 220, 150);  
  MyForm.Caption:='My dynamic created form';

  MyButton:=TButton.create(MyForm);  
  MyButton.Caption:='Close my form';
  MyButton.SetBounds(10, 10, 200, 30);
  MyButton.Parent:=MyForm;

  MyButton.OnClick:=@MyButtonClick;     

  MyForm.ShowModal;                     

  FreeAndNil(MyForm);     
end;

Note: もしコンポーネントが所有者(TButton.Create(Owner: TComponent))から生成されると、それはコンポーネントを解放する責任のある所有者に属する。そのため、MyButtonはMyFormを解放することによって自動的に解放される。

pascal
TForm1 = class(TForm)
...
private
  { private declarations }
  procedure MyButtonClick(Sender: TObject);
pascal
procedure TForm1.MyButtonClick(Sender: TObject);
begin
  Showmessage('Attention, closing my dynamically created form!');
  if Sender is TButton then
    TForm(TButton(Sender).Parent).Close;
end;

以下も参照のこと


From the Free Pascal wiki, page "Form Tutorial/ja", as it stood on 2024-03-25 after a change by Ariben, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 2, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.