Gestion de plusieurs formulaires sous Lazarus

1. Deux formulaires

Nous allons créer une fenêtre pop-up avec Form1 (formulaire principal) et Form2 (fenêtre secondaire)

1. Étapes de réalisation

  1. Créez un nouveau projet, glissez un Button1 sur Form1, définissez Caption = Open Form2 et générez l’événement OnClick (double-cliquez directement sur le bouton dans le concepteur pour créer rapidement l’événement de clic) ;
  2. Utilisez le menu supérieur File → New Form pour créer Form2 ;
  3. Ajoutez un Button1 sur Form2, attribuez Caption = Close et créez son événement OnClick ;
  4. Raccourcis pour naviguer entre formulaires : Shift+F12 ouvrir la liste des formulaires / F12 basculer entre vue conception et code ;
  5. Référencer Unit2 dans Unit1 : ajoutez Unit2 dans la section interface uses.

Unit1 (formulaire principal)

Deux points essentiels à respecter : Unit2; // Import de Unit2

Le second point se trouve dans la procédure de clic : ouvrir Form2 en mode modal avec Form2.ShowModal; // Affichage modal de Form2

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit2; // Import 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; // Affichage modal de Form2
end;

end.

Unit2 (formulaire secondaire)

Ajouter le second formulaire au projet

Après l’ajout, un nouvel onglet apparaît dans l’éditeur de code

Un onglet contient le code du formulaire principal, l’autre le code backend de Form2

Pour modifier Form2, sélectionnez Unit2 et appuyez sur F12 pour ouvrir sa fenêtre de conception

Ajoutez un bouton, définissez son libellé sur Close et implémentez la fermeture comme vu dans les leçons précédentes. Vous pouvez réaliser cette étape vous-même.

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; // Fermer le Form2 actuel
end;

end.

2. Différences clés entre Show et ShowModal (exemple comparatif)

Modification de l’interface

Ajoutez deux boutons sur Form1 :

  • btnShow : Caption = Show
  • btnShowModal : Caption = ShowModal
// Non-modal avec Show
procedure TForm1.btnShowClick(Sender: TObject);
begin
  Form2.Show;
  ShowMessage('Form2 est ouvert, le formulaire principal reste utilisable');
end;

// Modal avec ShowModal
procedure TForm1.btnShowModalClick(Sender: TObject);
begin
  Form2.ShowModal;
  ShowMessage('Ce message n’apparaît qu’après avoir fermé Form2');
end;Langage du code : JavaScript (javascript)

Explication des écarts

  1. Show (non-modal)
  • L’exécution du code se poursuit immédiatement après l’ouverture du formulaire secondaire ;
  • Le formulaire principal est déplaçable et ses autres boutons cliquables ;
  • Équivaut à Form2.Visible := True; et place automatiquement la fenêtre au premier plan.
  1. ShowModal (fenêtre modale)
  • L’exécution du code est suspendue tant que le formulaire secondaire n’est pas fermé ;
  • Le formulaire principal est verrouillé, impossible d’interagir avec lui ;
  • C’est une fonction qui renvoie une valeur ModalResult pour savoir comment la fenêtre a été fermée.

En résumé : une fenêtre modale vous oblige à fermer la fenêtre secondaire avant de manipuler le formulaire principal ; une fenêtre non-modal permet d’utiliser les deux en même temps.

3. Appels croisés entre formulaires : corriger l’erreur de référence circulaire

Besoin : Form1 ouvre Form2, Form2 ouvre Form1
Si vous ajoutez des références mutuelles dans interface uses, une erreur de dépendance circulaire survient. Solution : placer les références dans la section 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; // Placer la référence ici
{$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éférences croisées dans l’implémentation
{$R *.lfm}

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

4. Passer des valeurs entre formulaires (exemple avec variable membre publique)

Fonctionnalité : incrémenter un compteur à chaque ouverture du formulaire secondaire depuis le principal ; le second formulaire affiche le nombre d’ouvertures

Définir une variable entière publique dans Unit2

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
  public
    Count: Integer; // Variable publique accessible depuis Unit1
  end;

Incrémenter le compteur au clic sur le bouton de Unit1

procedure TForm1.Button1Click(Sender: TObject);
begin
  Inc(Form2.Count); // Augmenter le compteur de 1
  Form2.ShowModal;
end;Langage du code : JavaScript (javascript)

Afficher le nombre d’ouvertures dans Unit2

procedure TForm2.Button1Click(Sender: TObject);
begin
  ShowMessage('Ce formulaire a été ouvert '+IntToStr(Count)+' fois');
end;Langage du code : JavaScript (javascript)

Bonne pratique de développement : limiter l’usage des variables globales ou publiques ; préférez les propriétés Property pour transmettre des valeurs.

5. Créer des formulaires dynamiquement

Sans recourir aux variables globales de formulaire générées automatiquement par le projet

Méthode 1 : instanciation dynamique d’un Form2 déjà conçu

  1. Ouvrez le fichier Project.lpr et supprimez la ligne Application.CreateForm(TForm2, Form2);
  2. Code du bouton sur Form1 :
procedure TForm1.Button1Click(Sender: TObject);
var
  frm2: TForm2;
begin
  frm2 := TForm2.Create(nil); // Création manuelle de l’instance
  frm2.ShowModal;
  FreeAndNil(frm2); // Libérer la mémoire pour éviter les fuites
end;Langage du code : JavaScript (javascript)

Méthode 2 : formulaire entièrement généré par code (sans conception préalable)

Un clic sur le bouton génère une nouvelle fenêtre complète avec un bouton de fermeture intégré

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); // Gestionnaire de clic pour bouton dynamique
  public
  end;

var Form1: TForm1;

implementation
{$R *.lfm}

procedure TForm1.DynamicBtnClick(Sender: TObject);
begin
  ShowMessage('Fermeture du formulaire dynamique en cours');
  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 := 'Formulaire généré dynamiquement';

  // Créer un bouton propriétaire de MyForm, détruit automatiquement à la fermeture
  MyBtn := TButton.Create(MyForm);
  MyBtn.SetBounds(10,10,200,30);
  MyBtn.Caption := 'Fermer la fenêtre';
  MyBtn.Parent := MyForm;
  MyBtn.OnClick := @DynamicBtnClick;

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

Boîte de dialogue « Choose Debug Information format » s’affiche

Il suffit de configurer le format de débogage pour résoudre ce problème.

Gestion de plusieurs formulaires sous Lazarus

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *