Lazarus 複数フォームの使い方解説

1. 2つのフォーム

ポップアップ機能を実装します。Form1(メインフォーム)+Form2(ポップアップウィンドウ)の構成で作成します

1. 操作手順

  1. 新規プロジェクトを作成し、Form1にButton1を配置。Caption = Open Form2に変更し、OnClickイベントを作成します。フォームデザイン画面でボタンをダブルクリックすると素早くクリックイベントを生成可能;
  2. 上部メニュー File → New Form からForm2を作成;
  3. Form2にButton1を配置し、Caption = Close を設定して OnClick イベントを作成;
  4. フォーム切り替えショートカット:Shift+F12 フォーム一覧表示 / F12 デザイン画面・ソースコード画面切り替え;
  5. Unit1からUnit2を参照:interface uses の中に Unit2 を追加。

Unit1(メインフォーム)

注意点は2箇所あります。Unit2; // Unit2を読み込む

もう一箇所はクリック処理内で、モーダルウィンドウとしてForm2を開く記述です:Form2.ShowModal; // Form2をモーダル表示

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit2; //Unit2をインポート 

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.ShowModal; // Form2をモーダル表示
end;

end.

Unit2(サブフォーム)

プロジェクトに2番目のフォームを追加する手順

追加完了後、エディタ上部にタブが1つ増えます

一方がメインウィンドウ、もう一方がForm2のソースコードタブとなります

Form2を編集したい場合はUnit2タブを選択しF12キーを押すと、Form2のデザイン画面が開きます

前回の講義通りにボタンを追加し、キャプションをCloseに変更して閉じる処理を実装します。以前学習した内容なので各自で作成可能です。

unit Unit2;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm2 }

  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private

  public

  end;

var
  Form2: TForm2;

implementation

{$R *.lfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
  Close; // 現在のForm2を閉じる
end;

end.

2. Show と ShowModal の根本的な違い(比較サンプル)

画面レイアウト修正

Form1にボタンを2つ追加します:

  • btnShow:Caption = Show
  • btnShowModal:Caption = ShowModal
// 非モーダル Show
procedure TForm1.btnShowClick(Sender: TObject);
begin
  Form2.Show;
  ShowMessage('Form2が開かれました。メインフォームの操作は可能です');
end;

// モーダル ShowModal
procedure TForm1.btnShowModalClick(Sender: TObject);
begin
  Form2.ShowModal;
  ShowMessage('Form2を閉じないとこのメッセージは表示されません');
end;Code language: JavaScript (javascript)

違いの解説

  1. Show(非モーダルウィンドウ)
  • サブフォームを開いた直後にコード実行が続行;
  • メインフォームのドラッグや他ボタンのクリックが自由;
  • Form2.Visible := True; と同等、自動的に最前面に表示される。
  1. ShowModal(モーダルポップアップ)
  • サブフォームを閉じるまでコード実行が一時停止;
  • メインフォームがロックされ操作不可;
  • 戻り値 ModalResult からウィンドウの閉じ方を判定できる関数。

一言でまとめると:モーダルウィンドウはサブウィンドウを閉じるまでメイン側を操作できない。非モーダルは両方のウィンドウを同時に操作可能です。

3. フォーム同士の相互呼び出し:循環参照エラーの解消方法

要件:Form1からForm2を開き、Form2からForm1を開く
interface uses に相互参照を記述すると循環ユニットエラーが発生します。解決策:参照記述をimplementationブロックへ移動

Unit1

unit Unit1;

interface
uses Forms,StdCtrls;

type
  TForm1=class(TForm)
    Button1:TButton;
    procedure Button1Click(Sender:TObject);
  end;
var Form1:TForm1;

implementation
uses Unit2; // こちらに参照を記述
{$R *.lfm}

procedure TForm1.Button1Click(Sender:TObject);
begin
  Form2.Show;
end;
end.

Unit2

unit Unit2;

interface
uses Forms,StdCtrls;

type
  TForm2=class(TForm)
    Button1:TButton;
    procedure Button1Click(Sender:TObject);
  end;
var Form2:TForm2;

implementation
uses Unit1; // 相互参照は実装ブロックに記載
{$R *.lfm}

procedure TForm2.Button1Click(Sender:TObject);
begin
  Form1.Show;
end;
end.

4. フォーム間で値を受け渡す(公開メンバ変数による例)

機能:メインフォームからサブフォームを開くたびカウントを加算、サブフォームから開いた回数を確認できる

Unit2に公開整数型変数を定義

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
  public
    Count: Integer; // Unit1からアクセス可能な公開変数
  end;

Unit1のボタンクリックでカウントをインクリメント

procedure TForm1.Button1Click(Sender: TObject);
begin
  Inc(Form2.Count); // カウントを+1
  Form2.ShowModal;
end;Code language: JavaScript (javascript)

Unit2で開いた回数をポップアップ表示

procedure TForm2.Button1Click(Sender: TObject);
begin
  ShowMessage('このフォームは '+IntToStr(Count)+' 回開かれています');
end;Code language: JavaScript (javascript)

コーディング規約推奨:グローバル・公開変数は極力使用せず、Propertyプロパティによる値渡しを推奨します。

5. フォームを動的に生成する

プロジェクト自動生成のグローバルForm変数に依存しない実装

方法1:事前デザイン済みForm2を動的生成

  1. Project.lpr を開き、Application.CreateForm(TForm2, Form2); の行を削除
  2. Form1のボタンコード:
procedure TForm1.Button1Click(Sender: TObject);
var
  frm2: TForm2;
begin
  frm2 := TForm2.Create(nil); // 手動でインスタンス作成
  frm2.ShowModal;
  FreeAndNil(frm2); // メモリリーク回避のため解放
end;Code language: JavaScript (javascript)

方法2:コードのみで完全にフォーム作成(事前デザイン不要)

ボタンクリック時に新規ウィンドウと閉じるボタンをコードから生成

unit Unit1;

interface

uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure DynamicBtnClick(Sender: TObject); // 動的ボタン用クリックイベント
  public
  end;

var Form1: TForm1;

implementation
{$R *.lfm}

procedure TForm1.DynamicBtnClick(Sender: TObject);
begin
  ShowMessage('動的作成ウィンドウを閉じます');
  TForm(TButton(Sender).Parent).Close;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyForm: TForm;
  MyBtn: TButton;
begin
  MyForm := TForm.Create(nil);
  MyForm.SetBounds(100,100,220,150);
  MyForm.Caption := '動的生成フォーム';

  // ボタン作成、所有者をMyFormにするとウィンドウ破棄時自動解放
  MyBtn := TButton.Create(MyForm);
  MyBtn.SetBounds(10,10,200,30);
  MyBtn.Caption := 'ウィンドウを閉じる';
  MyBtn.Parent := MyForm;
  MyBtn.OnClick := @DynamicBtnClick;

  MyForm.ShowModal;
  FreeAndNil(MyForm);
end;
end.

「Choose Debug Information format」のダイアログが表示される場合

デバッグ情報フォーマットを設定するだけで正常に動作します。

Lazarus 複数フォームの使い方解説

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です