Réalisation d`une Interface Graphique avec Lazarus
Transcription
Réalisation d`une Interface Graphique avec Lazarus
Réalisation d'une Interface Graphique avec Lazarus
Auteur: E. Thirion - Dernière mise à jour : 17/10/2013
Cet exercice a pour but de vous familiariser avec les principes de réalisation d'une interface graphique en
utilisant LAZARUS. Ces principes se retrouvent dans d'autres logiciels de programmation comme Visual
Basic ou Visual C++.
Mise en route
●
Lancez Lazarus en cliquant sur son icone.
●
Si vous récupérez un ancien projet, sélectionnez l'entrée Nouveau Projet dans le menu projet.
Choisir Application, puis faire Ok.
●
Enregistrez tout de suite le projet dans le dossier Exo-ProgObjet1/IHM. Pour cela, sélectionnez
l'entrée Enregistrer du menu Fichier. LAZARUS vous demandera ensuite d'enregistrer deux
fichiers:
○
Il vous propose tout d'abord d'enregistrer Unit1.pas. C'est le code Pascal associé au formulaire
du projet. Changez ce nom en ihm.pas. Enregistrer ce fichier dans le dossier IHM.
○
Il vous propose ensuite d'enregistrer project1.lpi. Ce fichier décrit l'organisation globale du
projet. Renommez ce fichier en projet_ihm.lpi, puis enregistrez le dans le même dossier.
Première Partie : Placement des composants sur le formulaire
L'interface se construit en placant successivement les composants sur le formulaire. Pour cela, il faut utiliser
la palette des composants, qui est composé de plusieurs onglets. Nous utiliserons la palette des
composants standards ainsi que la palette des boites de dialogue.
Dans la palette des composants standards, nous utiliserons les composants suivants:
Bouton
Zone de liste
Etiquette
Group box
Zone de texte
Bouton radio
Menu principal
Case à cocher
Mémo
Page 1
Dans la palette des boites de dialogues, nous utiliserons deux boites de dialogue permettant d'ouvrir ou
d'enregistrer un fichier :
Boite de dialogue d'ouverture de fichier (TOpenDialog)
Boite de dialogue de fermeture de fichier (TSaveDialog)
Pour déposer un composant sur le formulaire, il suffit de cliquer sur ce composant dans la palette, puis sur le
formulaire à l'endroit où on souhaite le déposer.
Déposez les composants suivants sur le formulaire, en respectant à peu près la disposition:
Le composant sans nom au-dessus du bouton Button2 est une zone de liste.
Le mémo sert à afficher du texte sur plusieurs lignes et à le modifier éventuellement.
Les boutons radio permettent un choix unique parmis plusieurs, à condition qu'ils soient inclus dans un
même Group Box. Dans le cas contraire, les choix ne s'excluent pas.
Pour mettre des composants à l'intérieur d'un autre, il vaut mieux commencer par le plus gros (le conteneur
donc) puis déposer les petits composant dedans.
Si on procède dans le sens inverse, les petits composants seront cachés par le gros. Dans ce cas, il faut
faire un clic droit sur le conteneur , puis sélectionnez Z-Order, puis déplacer en arrière.
Si vous compilez le programme à ce stade vous constaterez que les composants MainMenu1 (menu
principal), OpenDialog1 et SaveDialog1 n'apparaissent pas. Ce sont des composants invisibles. Le fait de
les déposer sur le formulaire permet simplement d'indiquer qu'ils font partie de l'application.
Page 2
Création du menu
Ajoutons à présent une barre de menu. Pour cela, il faut double-cliquer sur le composant MainMenu1 ce qui
a pour effet d'ouvrir l'éditeur de menu.
Nous allons tout d'abord créer trois menus dans la barre de menu: faites un clic droit sur New Item1, puis
sélectionnez Insérer un élément après. Cela créé un deuxième menu New Item2 à droite du premier.
Procédez de même pour créer un troisième menu New Item3 à droite du deuxième. Vous devez alors
obtenir ceci:
Pour l'instant, les trois menus ne contiennent aucune entrée. Pour cela, il faut créer un sous-menu à
l'intérieur de chaque menu.
Commencez par créer quatre entrées dans le premier menu: faites un clic droit sur New Item1 et
sélectionnez Créer un sous-menu. Cela vous créera une première entrée de menu nommé New Item4.
Pour en ajouter une deuxième, faite un clic droit sur New Item4 et sélectionnez Insérer un nouvel élément
après. Vous obtenez ainsi un New Item 5 juste en dessous de New Item 4. Procédez de même pour
ajouter New Item 6, puis New Item 7 en-dessous de New Item 4. Vous devez obtenir ceci:
En procédant de la même manière, ajoutez un sous-menu à deux entrées (New Item 8 et 9) dans le
deuxième menu et dans le troisième (New Item 10 et 11) .
Page 3
Etat du projet à la fin de la première partie
Arrivé à ce stade, l'exécution du programme devrait vous afficher le formulaire suivant:
Remarquez que le nom de la zone de texte (Edit1) et du mémo (Mémo1) apparaissent à l'intérieur de ces
composants. Nous verrons comment les effacer ultérieurement.
Sans avoir rien programmé, certains composants réagissent déjà aux actions de la souris et du clavier. Le
menu principal devrait réagir de la manière suivante:
Clic sur New Item1
Clic sur New Item2
Clic sur New Item3
Vérifiez également que:
●
Il est possible de saisir du texte dans la zone de texte ainsi dans le memo. Par contre, c'est
impossible dans la zone de liste.
●
La case à cocher et les boutons radio peut être cochés et décochés. Lorsqu'un bouton radio est
coché, les autres sont automatiquement déchochés.
●
Un clic sur un bouton est sans effet.
Page 4
Représentation informatique des composants
Dans l'inspecteur d'objet, vous verrez apparaitre les objets sous la forme (Nom : Type) que vous avez
générés. Il apparaissent également dans le code, sous la forme d'une classe TForm1 générée
automatiquement par LAZARUS et d'une variable ( Form1 ) de ce type qui représente le formulaire:
Composants affichés par l'inspecteur d'objet
Classe générée par Lazarus dans IHM.pas
TForm1 = class (TForm)
Button1: TButton;
Button2: TButton;
CheckBox1: TCheckBox;
Edit1: TEdit;
GroupBox1: TGroupBox;
Label1: TLabel;
ListBox1: TListBox;
MainMenu1: TMainMenu;
Memo1: TMemo;
MenuItem1: TMenuItem;
MenuItem10: TMenuItem;
MenuItem11: TMenuItem;
MenuItem2: TMenuItem;
MenuItem3: TMenuItem;
MenuItem4: TMenuItem;
MenuItem5: TMenuItem;
MenuItem6: TMenuItem;
MenuItem7: TMenuItem;
MenuItem8: TMenuItem;
MenuItem9: TMenuItem;
OpenDialog1: TOpenDialog;
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
RadioButton3: TRadioButton;
SaveDialog1: TSaveDialog;
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
Page 5
Deuxième partie: définition des propriétés des composants
Chaque composant possède un certain nombre de propriétés que l'on peut visualiser et modifier via l'onglet
Propriétés de l'inspecteur d'objet.
Pour modifier une propriété d'un composant, il suffit de le sélectionner en cliquant dessus, de sélectionner la
propriété à modifier en cliquant sur cette propriété et enfin de modifier sa valeur.
Définition des libellés
Les libellés sont les titres que l'on donne aux composants affichés sur le formulaire. Ils sont représentés par
la propriété Caption.
Vous constaterez que cette propriété contient initialement le nom du composant. Cela explique pourquoi le
bouton Button1 est actuellement libellé Button1 et de même pour tous les autres composants du
formulaire.
Tout les composants n'ont pas forcément un libellé. Par exemple, les composants qui sont destinés à
contenir du texte, n'en ont pas. Sinon le libellé occuperait la place du texte. Pour leur donner un titre, il faut
utiliser une étiquette (composant de type TLabel) que l'on disposera juste à coté et sur laquelle on pourra
inscrire le libellé du composant.
Définissez les libellés des composants du formulaire de la manière suivante (attention: pour définir les
libellés du menu, il faut utiliser l'éditeur de menu):
Menu
Composant
Libellé
Composant
Libellé
Form1
IHM
MenuItem1
Fichier
Button1
Ajouter
MenuItem2
Voir
Button2
Initialiser
MenuItem3
Cacher
Label1
Composant
MenuItem4
Ouvrir
CheckBox1
Mémo non éditable
MenuItem5
Ouvrir Composant.txt
GroupBox1
Alignement
MenuItem6
Enregistrer
RadioButton1
Gauche
MenuItem7
Quitter
RadioButton2
Centré
MenuItem8
Sélection
RadioButton3
Droit
MenuItem9
Tout
MenuItem10
Sélection
MenuItem11
Tout
Définition des noms
Les noms des composants sont générés automatiquement et par conséquent, ils ne sont pas du tout
évocateurs: Button1 pour le premier bouton, Button2 pour le deuxième ... etc.
Ils sont stockés dans la propriété Name de chaque composant.
Pour rendre le code plus lisible, il vaut mieux nommer chaque composant par un nom qui rappelle sa
fonction.
Pour que le nom rappelle également le type du composant, je propose de préfixer le nom par deux lettres qui
rappellent son type. Par exemple Bt pour bouton, Zl pour zone de liste, Cc pour case à chocher, etc.
Page 6
Définissez les noms des composants de la manière suivante:
Menu
Composant
Nom
Composant
Libellé
Label1
EtComposant
MainMenu1
MnPrincipal
Edit1
ZtComposant
MenuItem1
MnFichier
Form1
FrIHM
MenuItem2
MnVoir
Button1
BtAjouter
MenuItem3
MnCacher
Button2
BtInit
MenuItem4
MnFichierOuvrir
ListBox1
ZlComposant
MenuItem5
MnFichierOuvrirComp
Memo1
MmFichier
MenuItem6
MnFicherEnregistrer
CheckBox1
CcMemoNonEditable
MenuItem7
MnFichierQuitter
GroupBox
GbAlignement
MenuItem8
MnVoirSelection
RadioButton1
BrAlignGauche
MenuItem9
MnVoirTout
RadioButton2
BrAlignCentre
MenuItem10
MnCacherSelection
RadioButton3
BrAlignDroit
MenuItem11
MnCacherTout
OpenDialog1
BdOuvrir
SaveDialog1
BdEnregistrer
Autres propriétés
La propriété Checked (Cases à cocher et Bouton Radio)
Les cases à cocher et les boutons peuvent être coché ou decoché par l'utilisateur ou par le programme. Par
défaut, ils sont décochés. Pour les rendre cochés au démarrage du programme, il faut mettre la propriété
checked à True.
Dans notre cas, nous allons définir l'alignement par défaut du mémo comme étant l'alignement à gauche. Il
faudra donc donner la valeur true à la propriété checked du bouton radio BrAlignGauche.
Les propriétés ExtendedSelect et MultiSelect (Zones de liste)
Les zones de liste sont faites en principe pour faire un choix parmis les éléments affichés.
Par défaut, un seul élément peut être sélectionné. Mais nous arons besoin d'en sélectionner plusieurs à la
fois. Pour cela, il faut donner la valeur True à la propriété MultiSelect.
La propriété Text (Zone de Texte)
La propriété Text d'une zone de texte contient sa valeur. Par défaut, elle contient le nom du composant.
Effacer le nom qui apparait dans la propriété Text de la zone de texte afin qu'il n'apparaisse plus au
démarrage du programme.
La propriété Lines (memo)
La propriété Lines d'un memo contient le texte de ce mémo.
Initialement, le texte du mémo est le nom du mémo. Pour l'effacer, cliquez sur les ... à gauche de la propriété
Lines. Cela fera apparaitre un éditeur de chaine. Effacez le nom, puis cliquez sur Ok.
Page 7
La propriété Hint
Cette propriété existe pour la plupart des composants. Elle permet d'indiquer à l'utilisateur à quoi sert un
composant par un texte qui s'affiche dès que le pointeur de souris survole ce composant.
Pour que ces indications apparaissent, il faut les saisir dans la propriété Hint, puis donner la valeur True à la
propriété ShowHint.
Définissez les indications suivantes pour les deux boutons:
Bouton
Indication
BtAjouter
Copie la zone de texte dans la zone de liste
BtInit
Copie le fichier Composant.txt dans la zone de texte
La propriété Filter (Boite de Dialogue d'Ouverture ou de Fermeture de Fichier)
Les boites de dialogues d'ouverture et de fermeture de fichier (classe TOpenDialog et TSaveDialog) ont
une propriété nommé Filter. Cette propriété permet de filtrer les fichiers possédant une certaine extension.
Cela permet d'éviter l'ouverture accidentelle d'un type de fichier non compatible avec le projet.
Dans notre cas, comme nous souhaitons travaillez avec des fichiers texte, il faudra uniquement accepter les
fichiers d'extension txt. Pour cela, cliquez sur la propriété Filter, puis sur les ... Cela vous ouvre l'éditeur de
filtre. Tapez "*.txt" dans la colonne filtre, puis cliquez sur Ok.
Effectuez cette opération pour les deux boites de dialogue BdOuvrir et BdEnregistrer.
Etat du projet après définition des propriétés
Compilez et exécuter à présent votre programme.
Le formulaire devrait avoir l'allure suivante:
Vérifiez qu'une indication s'affiche lorsque vous survolez les bouton Ajouter et Initialiser.
Le menu doit à présent avoir l'allure suivante:
Page 8
Menu Fichier
Menu Voir
Menu Cacher
Comme nous avons modifié les noms des composants, ils ont automatiquement été mis à jour dans le
programme:
Composants affichés par l'interpréteur d'objet
Classe générée par Lazarus dans IHM.pas
TFrIHM = class (TForm)
BtAjouter: TButton;
BtInit: TButton;
CcMemoNonEditable: TCheckBox;
ZtComposant: TEdit;
GbAlignement: TGroupBox;
EtComposant: TLabel;
ZlComposant: TListBox;
MnPrincipal: TMainMenu;
MmFichier: TMemo;
MnFichier: TMenuItem;
MnCacherSelection: TMenuItem;
MnCacherTout: TMenuItem;
MnVoir: TMenuItem;
MnCacher: TMenuItem;
MnFichierOuvrir: TMenuItem;
MnFichierOuvrirComp: TMenuItem;
MnFichierEnregistrer: TMenuItem;
MnFichierQuitter: TMenuItem;
MnVoirSelection: TMenuItem;
MnVoirTout: TMenuItem;
BdOuvrir: TOpenDialog;
BrAlignGauche: TRadioButton;
BrAlignCentre: TRadioButton;
BrAlignDroit: TRadioButton;
BdEnregistrer: TSaveDialog;
private
{ private declarations }
public
{ public declarations }
end;
var
FrIHM: TFrIHM;
Page 9
Troisième partie : Ecriture des gestionnaires d'évènement
Dans cet exercice, nous allons aborder les évènements suivants:
Evenement
Nom de l'évènement dans LAZARUS
Le clic
Click
Le double clic
DblClick
L'appuie d'une touche du clavier.
KeyDown
Le relachement d'une touche du clavier.
KeyUp
Le démarrage du programme
Create
L'arrêt du programme (par fermeture de la fenêtre
par exemple)
Close
Le changement de valeur d'une zone de texte ou
changement d'état (coché/décoché) d'un bouton
radio ou d'une case à cocher.
Change
Pour ouvrir un gestionnaire d'évènement, vous avez deux manières de procéder:
●
Par un double clic sur le composant: cela vous ouvre le gestionnaire de l'évènement par défaut. Par
exemple un double clic sur un bouton, vous ouvre automatiquement le gestionnaire du clic. Un
double clic sur le formulaire, vous ouvre automatique le gestionnaire de l'évènement Create .. etc
●
Via l'onglet évènement de l'inspecteur d'objet: vous cliquez d'abord sur le composant, puis vous
sélectionnez l'entrée qui correspond à l'évènement. Son nom est On suivi du nom de l'évènement.
Par exemple, OnChange pour l'évènement Change. Ensuite vous cliquez sur les ...
Pour mettre à jour un gestionnaire d'évènement existant, procédez de la même manière. LAZARUS vous
positionnera automatiquement sur le gestionnaire dans l'éditeur de code.
I - Gestion du mémo
Dans cette partie de l'exercice nous allons nous occuper de tous les composants liés à la gestion du mémo:
le menu Fichier, les boutons radio et la case à cocher.
I - 1 Chargement d'un fichier dans le mémo
Cette opération est réalisée par un clic sur l'entrée Ouvrir du Menu fichier qui devra déclencher l'affichage
de la boite de dialogue d'ouverture de fichier ( BdOuvrir ), puis le chargement du fichier sélectionné dans le
mémo.
Voici les informations utiles, pour coder le gestionnaire d'évènement correspondant :
●
pour faire appaitre la boite de dialogue, appliquez lui la méthode Execute.
●
après sélection du fichier par l'utilisateur, l'attribut FileName de la boite de dialogue contiendra son
nom.
I - 2 Sauvegarde du mémo dans un fichier
La sauvegarde du mémo dans un fichier s'obtient par un clic sur l'entrée Enregistrer du menu Fichier. Le
principe est le même que pour le chargement d'un fichier dans le mémo, sauf que vous utiliserez cette fois ci
la boite de dialogue BdEnregistrer et la méthode SaveToFile dont le paramètre est le nom du fichier.
Page 10
I - 3 Chargement du fichier Composant.txt dans le mémo
Le fichier composant.txt est un fichier texte qui contient les noms de certains composants du projet. Ce
fichier nous servira par la suite à initialiser la zone de liste ZlComposant.
Le chargement de ce fichier dans le mémo se fait par un clic sur l'entrée Ouvrir Composant.txt du menu
fichier.
Pour ce fichier particulier, le mémo sera rendu non éditable. La case à cocher CcMemoNonEditable devra
donc être coché.
Information utiles
●
Pour rendre un mémo non éditable, sa propriété Enabled doit avoir la valeur False.
●
Pour cocher une case à cocher, il suffit d'affecter la valeur True à sa propriété Checked.
I - 4 Activation et désactivation du mémo
Le mémo doit pouvoir être activé ou désactivé (rendu non éditable) par l'intermédiaire de la case à cocher
Mémo non éditable.
Le changement d'état (coché/décoché) d'une case à coché est un évènement de type Change (et non pas
clic ! ). C'est l'évènement par défaut d'une case à cocher. Il vous suffira donc de double cliquer sur la case à
cocher pour ouvrir le gestionnaire de cet évènement.
Remarquez que la valeur de la propriété Checked est automatiquement mis à jour lorsque l'utilisateur coche
ou décoche une case à cocher.
I - 5 Justification du mémo
Il s'agit ici de réaliser la justification à gauche, au centre ou à droite par l'intermédiaire des boutons radios.
Le principe est le même que pour une case à cocher à part que deux boutons radios ne peuvent être cochés
en même temps.
L'alignement du texte dans le mémo est défini par la propriété Alignment à laquelle on affectera la valeur:
●
●
●
taLeftJustify pour un alignement à gauche
taCenter pour un alignement au centre
taRightJustify pour un alignement à droite.
II - Gestion de la zone de texte
La zone de texte ZtComposant nous permettra d'ajouter le nom d'un composant dans la zone de liste de
deux manières:
●
en cliquant sur le bouton Ajouter.
●
en faisant un double-clic dans la zone de texte.
Dans ces deux cas, il s'agira donc de transférer le contenu de la zone de texte dans la zone de liste.
On souhaiterait également que :
●
la zone de texte soit effacée lorsqu'on appuie sur la touche espace (code ascii 32).
●
un double clic sur le formulaire affiche son nom dans la zone de texte.
Page 11
III - Gestion de la visibilité des composants via la zone de liste
La zone de liste ZlComposant va nous permettre de sélectionner des composants que l'on pourra ensuite
rendre visibles/invisibles par les menus Voir et Afficher.
III-1 Chargement du fichier Composant.txt dans la zone de liste
Un clic sur le bouton Initialiser doit permettre de charger le fichier composant.txt dans la zone de liste.
Rappelez vous que le contenu d'une zone de liste se trouve dans son attribut Items appartenant à la classe
TStrings. Vous pouvez donc appliquer la méthode LoadFromFile à cet attribut pour charger le fichier dans
le mémo.
III-2 Cacher ou voir tous les composants de la zone de liste
L'entrée Tout dans les menus Voir et Cacher permet respectivement de rendre visible ou invisible tous les
composants dont le nom figure dans la zone de liste.
Pour vous éviter d'écrire le même code dans la question suivante, je vous conseille ici d'écrire deux
procédures:
●
une procédure permettant de rendre un composant invisible connaissant son nom.
●
une procédure permettant de rendre un composant visible connaissant son nom.
Attention: le composant en question ne figure pas forcément dans le fichier Composant.txt de départ, par
contre les méthodes Hide et Show doivent pouvoir lui être appliqué (voir pour cela l'arborescence d'héritage
entre les classes de composants qui figure dans le cours).
III-3 Cacher ou voir tous les composants sélectionnés
L'entrée Selection dans les menus Voir et Cacher permet respectivement de rendre visible ou invisible tous
les composants sélectionnés dans la zone de liste.
Pour effectuer une sélection multiple appuyer sur la touche CTRL avant de cliquer sur un élément. Vous
vérifirez que si vous donnez la valeur False à la propriété MultiSelect de la zone de liste, cette opération
n'est plus possible.
Pour mémoriser les éléments sélectionnés nous utiliserons un objet de type TStringList. Appelons le LES
(pour Liste des Elements Selectionnés).
Je vous conseille ici de définir une procédure permettant de construire cette liste. Cela vous permettra de la
réutiliser dans les deux gestionnaires de composant ainsi que pour la question suivante.
Pour savoir si un élément de la zone de liste a été sélectionné, utilisez l'attribut Selected. Cet attribut de
type booléen, indique si un élément d'indice donné a été sélectionné. Par exemple Selected[2] est vrai si le
3ème (car l'indicage commence à 0) élément est sélectionné.
IV - Suppression d'éléments sélectionnés dans la zone de liste
Ecrivez le gestionnaire d'évènement permettant de supprimer les éléments sélectionnés dans la zone de
liste lorsque l'utilisateur appuie sur la barre d'espace (code ASCII 32).
Vous pourrez utiliser ici les méthodes Delete et IndexOf de la classe TString : Delete( i ) supprime l'élément
d'indice i. IndexOf ( c ) : retourne l'indice de la chaine c.
Page 12
V - Arrêt du programme
Ecrivez tout d'abord le gestionnaire de l'évènement Close du formulaire. Vous y mettrez simplement
l'affichage d'un message d'adieu.
Dans un deuxième temps, écrivez le gestionnaire d'évènement de l'entrée Quitter du menu fichier. Dans ce
gestionnaire vous vous contenterez de déclencher l'arrêt du programme par la méthode Close (méthode de
la classe TForm).
Vous constaterez que le message d'adieu s'affiche également lorsque l'utilisateur quitte le programme via le
menu. Nous avons donc ici un exemple d'évènement déclenché par programme.
Page 13