Lazarus 多表單開發介紹

一、雙表單

實作彈窗功能,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(主表單)

有兩處重點須注意:Unit2; // 引入 Unit2

第二處則是點擊函式內,以模態視窗方式開啟第二個表單: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(子表單)

在專案內新增第二個表單

新增完成後,編輯器會多出一個分頁標籤

一個是主視窗,另一個是 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.

二、Show 與 ShowModal 核心差異(範例對照)

介面調整

在 Form1 新增兩顆按鈕:

  • 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 判斷視窗關閉方式。

簡單總結:模態模式開啟時,必須先關閉子視窗才能操作主視窗;非模態模式開啟子視窗後,仍可自由操作主視窗。

三、表單互相呼叫:解決循環引用錯誤

需求: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.

四、表單之間傳遞數值(公用成員變數範例)

功能說明:主表單點擊開啟子表單時計數,子表單可查詢累計開啟次數

在 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 進行參數傳遞。

五、動態建立表單

不依賴專案自動產生的全域 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 多表單開發介紹

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *