IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Introduction à Perl/Tk

Interfaces graphiques avec Perl


précédentsommairesuivant

I. Introduction à Perl/Tk

De nombreux et divers modules étendent les fonctionnalités de Perl. Ce livre traite du module Tk qui nous permet d'ajouter facilement une interface graphique à nos scripts Perl tout en continuant à utiliser toutes les possibilités qui font la grandeur de ce langage. Au lieu de nécessiter la saisie d'une commande plus ou moins compliquée, votre programme Perl/Tk est invoqué à l'aide d'une icône ou d'une simple commande et l'interface gère tout à partir de là.

L'extension Tk ne fait pas partie de la distribution standard de Perl(2). Vous devrez l'obtenir séparément à partir d'un site CPAN et l'installer. Lorsque ce sera fait, il vous suffira d'ajouter use Tk; au début de vos scripts Perl.

I-A. Perl (et Tk)  : un peu d'histoire

Au départ, Perl a été écrit comme une solution rapide à un problème que Larry WALL avait avec son travail. Comme toutes les personnes qui s'estiment paresseuses, il trouva un moyen meilleur et plus facile de procéder : Perl était né. Il a, depuis, évolué pour devenir un langage très répandu et bien utilisé. Perl existe pour de nombreuses plates-formes différentes, est bien documenté et, cerise sur le gâteau, est gratuit. Évidemment, la raison pour laquelle vous lisez ce livre est que vous êtes déjà converti à Perl et que vous voulez savoir comment l'utiliser au mieux.

L'extension Tk de Perl gère tous les widgets, et toutes les petites choses qui, ensemble, créent une interface graphique. Elle a été adaptée par Nick ING-SIMM0NS à partir de Tcl/Tk afin d'être utilisable avec Perl. Une erreur classique consiste à croire que l'on doit installer Tcl/Tk en plus de Perl et Tk pour que tout fonctionne, alors que tout ce dont vous avez besoin est Perl et son extension Tk. Grâce au travail de beaucoup d'autres personnes, les paresseux autoproclamés comme moi peuvent télécharger le binaire pour leur machine puis l'installer en moins de dix minutes. Vous pouvez aussi le compiler pour votre machine à partir des sources.

I-B. Perl/Tk pour Unix et Windows 95/NT

Alors que j'écrivais ce livre et que je me rendais compte que je n'avais pas assez de machines chez moi pour l'écrire avec MS Word et tester les exemples de code sur ma machine Linux sans devoir redémarrer sans cesse pour passer d'un système d'exploitation à l'autre, un miracle survint. L'extension Tk pour Perl fut adaptée pour Windows. Windows désigne ici le système d'exploitation super-influent installé par défaut sur la plupart des ordinateurs personnels de nos jours, Microsoft Windows. La plupart des gens n'ont pas de compilateur C pour leur machine Windows, mais Gurasamy SARATHY a réalisé une très bonne distribution binaire de Perl et une sélection judicieuse d'extensions, dont Tk. Il vous suffit de la télécharger puis de lancer l'installation, et vous êtes prêt à travailler.

La façon d'écrire des applications Perl/Tk ne varie pas, que l'on emploie une machine sous Unix ou sous Windows. Vous pouvez utiliser n'importe quel éditeur de texte simple. Une petite différence existe quant à la manière de lancer les applications reportez-vous à l'annexe B, Différences entre systèmes d'exploitation, pour plus de détails. Pour le moment, je me contenterai de dire que je préfère lancer mes applications Perl sous Windows NT 4.0 (Service Pack 3) plutôt que sous Windows 95.

I-C. Versions

Lorsque j'ai commencé à écrire ce livre, les versions les plus récentes de Perl et de Tk étaient, respectivement, 5.003 et 400.202. Depuis, une version Win32 du module Tk a été développée et mise à disposition. Perl a aussi subi quelques changements. Juste avant l'impression de ce livre, l'adaptation de Tk800.007 était en phase bêta et Perl atteignait le numéro de version 5.004_68 (version bêta, également). J'ai tâché d'inclure les informations concernant les nouvelles versions de Tk et Perl et pour tester les exemples avec elles. Dans certains cas (les fontes, par exemple), certaines fonctionnalités significatives ont été ajoutées dans la nouvelle version de Tk. J'ai essayé de noter tous les changements là où ils s'appliquent mais, la plupart du temps, vous n'aurez pas à vous soucier de la version que vous utilisez(3).

I-D. Pourquoi utiliser une interface graphique ?

Vous avez évidemment acheté ce livre (ou vous êtes en train de penser à le faire) car vous avez quelques idées sur les raisons pour lesquelles vous pourriez vouloir utiliser une interface graphique pour l'un ou plusieurs de vos scripts. Dans le cas contraire, continuez à lire.

Comme vous êtes habitué à écrire des scripts Perl, vous connaissez les moyens d'y faire entrer et sortir des informations. Cela implique généralement une combinaison de lecture/écriture de fichiers, d'options de la ligne de commande et, éventuellement, de données lues ou écrites lors de l'exécution de l'application (STDIN/STDOUT, utilisation de tubes (|) ou de l'opérateur <>). Certaines applications peuvent s'exécuter sans nécessiter d'entrées et d'autres, comme les scripts d'installation, ont constamment besoin d'informations fournies par l'utilisateur Voulez-vous installer ce fichier ? Puis-je remplacer cette DLL ? Voulez-vous créer ce répertoire ? Voulez-vous installer les fichiers d'aide ? Parfois, vous pouvez configurer un ensemble de valeurs par défaut pour que l'utilisateur n'ait plus qu'à presser la touche 'Entrée' pour accepter, mais il doit quand même rester rivé sur son clavier pour attendre la question suivante. Ne serait-ce pas plus agréable de rassembler d'abord toutes ces informations puis de permettre à l'utilisateur de presser un bouton « Démarrer » pour exécuter toutes les étapes une fois que les décisions ont été prises ?

Une interface graphique donne l'impression qu'une application dispose d'un peu plus de potentialités et est plus professionnelle. Cependant, dans certains cas, ce serait du gâchis d'ajouter une telle interface à un script. Si tout ce que vous devez faire consiste à lire un fichier, faire quelques modifications ne nécessitant pas d'intervention de l'utilisateur, et recracher le tout dans un autre fichier, un GUI serait stupide et déplacé. Les interfaces graphiques sont adaptées aux cas où vous avez besoin d'un grand nombre de décisions et de saisies de l'utilisateur, comme dans notre exemple d'installation du paragraphe précédent.

Voici quelques exemples d'applications où l'utilisation d'une interface utilisateur graphique est justifiée :

  • un mini client web se connectant à un serveur-dictionnaire et vous permettant de rechercher des mots ;
  • une application prenant une expression rationnelle en entrée et affichant la liste des correspondances trouvées dans une fenêtre que l'on peut faire défiler ;
  • une application interrogeant une base de données et affichant les résultats des requêtes dans plusieurs widgets, avec des étiquettes indiquant ce que représentent les données affichées ;
  • un lecteur de courrier interrogeant votre boîte de réception et pouvant également envoyer des messages électroniques ;
  • parfois, votre patron dit « rendez-le simple à utiliser ! » et cela consiste habituellement soit à envelopper un script, soit à écrire une interface qui facilite la compréhension des utilisateurs quant aux décisions qu'ils doivent prendre. Vos utilisateurs peuvent aussi être plus à l'aise avec une interface graphique qu'avec une interface en ligne de commande.

I-E. Pourquoi utiliser Perl/Tk ?

Avez-vous déjà essayé de tracer une fenêtre en utilisant les possibilités « natives » ? Si vous le faites en C, il vous faudra développer à peu près 100 lignes de code, simplement pour créer le classique programme « Bonjour tout le monde »(4), que vous utilisiez Windows ou X Window. Ces lignes ne comprennent même pas l'ajout d'un bouton de sortie vous permettant de quitter proprement l'application.

Tout au long de ma vie de programmeur, j'ai utilisé plusieurs méthodes différentes pour tracer des fenêtres et créer des applications dotées d'interfaces utilisateur graphiques. Utiliser les fonctions X Window de base (comme X_Create_Line_from_x_to_y), est vraiment un fardeau. Elles offrent, il est vrai, un contrôle total sur tous les petits détails mais, là encore, vous devez gérer chacun d'eux. Parfois, j'apprécie de ne pas savoir exactement comment le bouton s'est tracé ; il me suffit de savoir qu'il l'a fait (je sais conduire une voiture sans pour autant comprendre exactement les détails intimes du moteur à explosion et j'apprécie de pouvoir tourner la clé de contact et réussir dans ma mission consistant à conduire jusqu'à mon travail).

Vous avez probablement vu plusieurs livres sur Tcl/Tk. Le problème de Tcl est que vous devez programmer en respectant les contraintes de ce langage. Je préfère vraiment en utiliser un que je connais déjà plutôt bien et y parfaire mes compétences.

Perl/Tk vous fait cadeau de tous les petits détails ennuyeux. Il gère la boucle des événements. Il gère le tracé des bords en 3D de vos boutons (si vous n'êtes pas certain de comprendre ce que je dis, patience : j'expliquerai tout cela en temps voulu). Vous pouvez simplement utiliser le langage Perl pour « placer un bouton ici » ce qui, traduit en véritable Perl, se dit

 
Sélectionnez
$mw->Button(-text => "quelque chose")->pack();

De plus, grâce à la merveilleuse communauté dont dispose Perl, il existe une multitude de types de widgets composés différents et prêts à l'emploi. Si vous ne pouvez pas trouver le widget parfait (tel qu'une sélection-à-listes-multiples avec son canevas associé, par exemple), il est assez simple de le créer en utilisant une combinaison de widgets et de constructions, soit de base, soit moins courants.

Du point de vue d'un programmeur, l'utilisation de Perl/Tk pour écrire une interface utilisateur graphique est quelque chose d'agréable : c'est le nirvana du développeur !

Avec simplement quelques lignes de code, vous pouvez instantanément afficher un bouton et plusieurs autres widgets qui ressembleront à une application complète. Bien sûr, cela prend un peu plus de temps pour coder le corps de tout cela, mais c'est presque aussi plaisant.

Tandis que vous progresserez dans la lecture de ce livre, le meilleur moyen de comprendre ce qui se passe sera d'essayer les nombreux exemples différents. II y a des tonnes de bouts de code inclus pour cette seule raison. Commencez par le programme de base « Bonjour tout le monde » et modifiez les options du bouton lorsque vous passerez aux chapitres 2 et 3. Examinez les résultats sur votre propre écran.

Vous pouvez aussi tester les outils suivants (que nous ne traitons pas dans ce livre, mais qui sont pratiques à utiliser) : tkpsh et ptksh (ils sont apparus avec Tk800.007, la dernière version de Tk pour Perl). Vous pouvez les télécharger à partir du site http://www.monmouth.com/~beller. Ces deux programmes vous permettent de taper du code sur STDIN et d'évaluer chaque instruction (un peu comme wish).

À ce jour (15/04/2018), La version de TK la plus à jour n'est évidemment plus la version TK8000.007 et le lien ci-dessus n'est plus fonctionnel.

I-F. Installation du module Tk

Avant d'aller plus loin dans les détails d'utilisation de Perl/Tk, nous devons traiter de son installation. Il existe plusieurs façons d'obtenir Perl et Tk et de les installer sur votre machine. Vous pouvez récupérer les sources et les compiler (c'est facile avec Unix, moins avec Windows), ou obtenir une distribution binaire et l'installer. Certaines de ces distributions peuvent ne pas inclure tous les composants voulus, aussi assurez-vous de lire tous les fichiers README contenus dans le paquetage.

Les deux principales distributions binaires de Perl pour Win32 sont disponibles auprès d'ACTIVESTATE (https://www.activestate.com) et de CPAN (https://www.perl.com). La distribution binaire de CPAN contient le module Tk et c'est donc elle que nous décrirons ici(5).

Vous devez d'abord installer Perl.

Pour savoir si le module Tk est déjà installé, utilisez cette commande(6) :

 
Sélectionnez
Perl -e 'use Tk'

Si vous n'obtenez pas d'erreur, vous pouvez continuer. Sinon, l'erreur ressemblera à ce message(7) :

 
Sélectionnez
Can't locate Tk.pm in @INC (@INC contains: C:\PERL\lib\site.
                            C:\PERL\lib c:\perl\lib c:\perl\lib\site 
                            c:\perl\lib\site .) at mon-script une 1.

Vous devrez rechercher le module Tk sur un site CPAN en commençant par : https://www.cpan.org/modules/by-module/Tk/

À partir de ce répertoire, recherchez les fichiers Tk*readine et Tk*tar.gz (essayez toujours de récupérer les dernières versions le * représente ici le numéro de version). Faites attention lorsque vous téléchargez le fichier .gz, car certains systèmes tentent de renommer celui-ci en .tar.tar : si c'est le cas, renommez simplement le fichier afin qu'il ait une extension .tar.gz et il se décompactera correctement. Suivez les instructions du fichier README afin de vous assurer de disposer de la bonne version de Perl. Après le téléchargement de Tk*tar.gz, vous devrez le décompacter en utilisant Winzip pour Windows, ou gunzip et tar -xvf pour Unix(8). Suivez ensuite les instructions contenues dans le fichier Install. Cela ressemble beaucoup à l'installation de Perl lui-même.

Recommencez le test perl -e 'use Tk' (ou perl -e "use Tk") afin de vous assurer que tout a fonctionné correctement. Que ce soit pour Windows ou pour Unix, vérifiez que le répertoire des binaires de Perl a été ajouté à votre variable d'environnement PATH. Vous pouvez alors utiliser le script de démonstration nommé widget pour connaître les types de widget disponibles.

I-G. Création des widgets

Tous les widgets sont créés selon le même principe de base, à part quelques exceptions. Chaque widget doit avoir un widget parent qui le surveille alors qu'il est créé et en garde une trace durant son existence. Lorsque vous créez une application, une fenêtre centrale contiendra tous les autres widgets. Habituellement, cette fenêtre sera la mère de tous les widgets qu'elle contient et de toutes les autres fenêtres que vous créerez dans votre application. Vous créez un ordre des widgets pour que les communications entre les widgets fils et parents puissent avoir automatiquement lieu sans intervention de votre part dès lors que vous avez tout mis en place.

En supposant que le widget $parent existe déjà, l'instruction classique de création d'un widget Widgettype sera:

 
Sélectionnez
$fils = $parent->Widgettype( [-option => valeur, . . . ]);

Remarquez que les variables qui stockent les widgets sont des scalaires. En fait, ce sont des références vers des objets widgets, mais vous n'avez pas besoin de le savoir pour l'instant. Si vous ne connaissez pas bien la programmation orientée objet avec Perl, sachez seulement que l'utilisation du signe -> entre $parent et Widgettype appelle la méthode Widgettype de l'objet $parent. Elle relie $parent au fils $fils. Comme vous pouvez vous en douter, $parent devient le parent du widget créé. Un parent peut avoir plusieurs fils, mais un fils n'a qu'un seul parent. Il n'y a presque rien à faire de plus ici que d'assigner des fils à leurs parents.

Lorsque vous appelez la méthode Widgettype, il y a habituellement des paramètres de configuration à passer pour configurer le widget et les interactions avec l'application. Les paramètres de configuration apparaissent par paires : une option et sa valeur associée. Vous verrez des options comme -text, -state ou -variable. Remarquez que les options commencent toutes par un tiret et que, même avec ce tiret, ce ne sont que des chaînes de caractères représentant des étiquettes qui indiquent la valeur suivante apparaissant dans la liste. Habituellement, il n'est pas nécessaire de mettre les options entre apostrophes, car Perl est suffisamment astucieux pour reconnaître qu'il s'agit de chaînes. Toutefois, si vous utilisez le commutateur -w, Perl peut se plaindre à propos d'une option dont il pense qu'il ne s'agit pas de texte. Pour éviter cela, vous pouvez mettre systématiquement toutes vos options entre apostrophes, mais ce ne devrait pas être nécessaire. Les noms des options sont toujours tout en minuscules (sauf dans quelques cas très rares, qui seront indiqués lorsque nous les aborderons).

Les options sont données sous la forme d'une liste identique à celle-ci :

 
Sélectionnez
(-option => valeur, -option => valeur, -option => valeur)

Ne soyez pas troublé par le curieux signe => ; c'est juste une autre façon de dire « virgule ». En fait, vous pourriez vous contenter d'utiliser celles-ci :

 
Sélectionnez
(-option, valeur, -option, valeur, -option, valeur)

Cependant, il est alors plus difficile de dire quelles sont les paires option/valeur. Si l'on considère les instructions suivantes comme syntaxiquement équivalentes (chacune d'elles crée un widget bouton de 10 pixels sur 10, affichant « Sortie » et réalisant l'action de quitter l'application lorsqu'il est pressé) :

 
Sélectionnez
$bouton = $parent->Button( -text, "Sortie", 
                           -command, sub { exit },
                           -width, 10, -height, 10 );
$bouton = $parent->Button( -text => "Sortie",
                           -command => sub { exit },
                           -width    => 10, -height => 10);

Les appariements des paramètres sont bien plus évidents dans la deuxième ligne. L'option doit être placée immédiatement avant la valeur qui lui est associée : -text est appariée avec "Sortie", -command a la valeur sub{exit}, et -width et -height ont toutes deux la valeur 10.

Bravo, nous n'avons pas encore terminé le premier chapitre que vous savez déjà lire une ligne typique de code Perl/Tk !

I-G-1. Définitions succinctes des widgets Toplevel, MainWindow et Frame

Le chapitre suivant présente la gestion de l'espace, et plusieurs des exemples utilisent des widgets dont vous ne savez encore rien. Dans la plupart des cas, leurs rôles sont faciles à deviner, mais nous proposerons parfois une courte description.

Un widget MainWindow (« fenêtre principale », en français) est une version spéciale de widget Toplevel (« premier niveau », en français). MainWindow et Toplevel sont tous les deux des fenêtres contenant d'autres widgets. La seule différence entre eux est qu'un MainWindow est la première fenêtre créée dans votre application. Ces deux widgets sont traités plus en détail dans le chapitre chapitre 13, Widgets de premier niveau.

L'autre type de widget que vous devez connaître est le widget Frame (« cadre », en français). Un cadre est un conteneur pouvant aussi contenir d'autres widgets. Habituellement, il est invisible et ne sert qu'à arranger les widgets selon vos désirs. Le chapitre 12, Cadres, est consacré au traitement du widget Frame.

Voici à quoi ressemble la création de chacun de ces widgets

 
Sélectionnez
$mw    = new MainWindow;       # ou $mw    = MainWindow->new();
$top   = $mw->Toplevel();
$frame = $mw->Frame( -borderwidth => 2, -relief => "groove" );

Pour le moment, il vous suffira de vous rappeler les significations générales des widgets MainWindow, Toplevel, et Frame.

I-H. Style de programmation

Les lignes de code d'un script Perl/Tk peuvent rapidement devenir lourdes à cause de toutes les paires option/valeur utilisées pour la définition et la configuration de chaque widget. Il y a plusieurs façons de formater le code pour traiter les problèmes de lisibilité (et, dans certains cas, d' « éditabilité »). Dans la majeure partie des cas, il suffit d'ajouter des espaces ou des tabulations supplémentaires pour mettre en évidence les différentes parties du code. Lorsque vous aurez l'habitude de lire du code, il ne vous apparaîtra plus aussi mystérieux et pesant.

Un des styles d'écriture place chaque paire option/valeur sur une ligne distincte (c'est celui que je préfère et que j'utilise tout le temps)

 
Sélectionnez
$bouton = $parent->Button(
    -text    => "mon texte",
    -command => sub { exit },
    -width   => 10,
    -height  => 10);

Avec ce style de codage, les paires sont évidentes, ainsi que les valeurs associées à chaque option (vous pouvez aussi pousser à l'extrême et aligner chaque => pour faire de belles colonnes, selon le temps que vous mettez à presser la barre d'espace). Certains préfèrent commencer les paires option/valeur sur la ligne suivante et placer le ); final sur sa propre ligne, après la dernière paire, qui conserve la virgule pour faciliter le formatage :

 
Sélectionnez
$bouton = $parent->Button(
    -text    => "mon texte",
    -command => sub { exit },
    -width   => 10,
    -height  => 10
);

Cela rend le code plus facile à modifier ; on peut ajouter ou supprimer une paire option/valeur sans devoir se bagarrer avec les parenthèses, les points-virgules ou les virgules. Cela permet aussi de garder les lignes suivantes plus près du côté gauche de la page afin d'éviter d'avoir un code partant trop à droite lorsque l'on a plusieurs niveaux d'indentation.

Parfois, lorsqu'il n'y a qu'une ou deux paires option/valeur, il semble naturel de les laisser toutes sur la même ligne et de garder un peu d'espace

 
Sélectionnez
$bouton = $parent->Button(-text => "mon texte", -command => sub { exit });

Vous finirez sûrement par utiliser un style adapté à la façon dont vous lisez et modifiez le code. Quel que soit celui que vous choisissez, essayez simplement d'être cohérent tout au long de vos scripts au cas où quelqu'un d'autre s'occuperait de la maintenance de votre code (cela pourrait même être vous, un an ou plus après l'avoir écrit).

I-I. Affichage d'un widget

On utilise deux méthodes distinctes pour créer et pour afficher un widget, bien qu'elles soient parfois confondues dans la même ligne, ce qui les fait ressembler à une méthode unique. Dans les exemples vus jusqu'à présent, nous avons utilisé Button pour créer le bouton, mais rien ne s'affiche en utilisant cette méthode seule. Au lieu de cela, vous devez utiliser un gestionnaire d'espace pour provoquer l'affichage du widget dans son widget père ou dans un autre widget. Le gestionnaire le plus souvent utilisé est pack et il suffit d'appeler la méthode pack sur l'objet $widget de la façon suivante :

 
Sélectionnez
$widget->pack();

Par exemple :

 
Sélectionnez
$bouton->pack();

On peut passer des paramètres à la méthode pack, mais nous les aborderons au chapitre 2, Gestion de l'espace.

Il n'est pas nécessaire d'appeler pack sur une ligne distincte. La notation ->pack peut être ajoutée à la création du widget :

 
Sélectionnez
$parent->Button(
    -text    => "Au revoir !",
    -command => sub { exit })->pack();

Les autres gestionnaires d'espace disponibles sont grid et place. Tous trois se comportent différemment et le choix de l'un plutôt qu'un autre dépend de l'aspect que vous voulez donner à votre application. Encore une fois, les informations sur les gestionnaires d'espace se trouvent dans le chapitre 2.

I-J. Anatomie d'une boucle d'événement

Lorsque vous programmez une application utilisant une interface graphique plutôt qu'en mode texte, il y a beaucoup de choses différentes à considérer. Dans une application en mode texte, vous pouvez lire sur l'entrée standard (STDIN), analyser les options de la ligne de commande, lire des fichiers ou demander des informations précises à l'utilisateur. Le clavier est le seul moyen d'entrée laissé à l'utilisateur. Dans une interface utilisateur graphique, les entrées peuvent ne pas venir que de là, mais aussi de la souris et du gestionnaire de fenêtres (comme c'est le cas de l'ordre de fermeture d'une fenêtre venant d'un gestionnaire comme mwm ou MS Windows). Bien que ces entrées supplémentaires rendent vos applications plus souples, elles compliquent aussi votre travail. Pourvu qu'on lui indique ce qu'il faut faire, Perl/Tk nous aide à gérer proprement toutes ces entrées supplémentaires.

Dans une interface utilisateur graphique, les entrées sont définies par des événements. Ceux-ci sont typiquement des combinaisons d'actions sur le clavier ou la souris, effectuées simultanément ou non. Si l'utilisateur presse le bouton gauche de la souris sur le bouton « B », il s'agit d'un certain type d'événement. Presser le bouton droit de la souris sur le bouton « C » serait un autre événement. Presser sur la touche 'a' du clavier en serait encore un autre. Un autre, enfin, serait de maintenir la touche 'Ctrl' pressée tout en cliquant avec le bouton central de la souris. Vous voyez le principe…

Les événements sont traités par une boucle de gestion des événements (event loop). Cette boucle fait exactement ce que son nom implique – elle gère les événements en boucle. Elle détermine les sous-programmes à appeler selon le type de l'événement survenu. Voici l'algorithme d'une telle boucle :

 
Sélectionnez
Tant Que non fini Faire
    obtenir des informations sur l'événement

    Si l'événement est un clic gauche de la souris Alors 
        appeler process_left_mouse_click
    Sinon Si l'événement est un clic droit de la souris Alors 
        appeler process_right_mouse_click
    Sinon Si l'événement est une frappe au clavier Alors
        appeler type-it
    Sinon
        gérer les événements d'affichage, de changement de taille, etc.
    Fin Si
Fin Tant Que

Évidemment, il s'agit ici d'une approche simplissime d'une boucle d'événement, bien qu'elle fasse quand même apparaître l'idée principale. Cette boucle est un processus de filtrage permettant de déterminer le type de l'entrée fournie à l'application. La fonction process_left_mouse_click, par exemple, pourrait déterminer où se trouvait le pointeur lorsque le clic souris est survenu, puis appeler d'autres fonctions en utilisant cette information.

En Perl/Tk, la boucle d'événement est lancée par l'appel d'une fonction nommée MainLoop (« boucle principale »). Tout ce qui se trouve avant cet appel concerne simplement la configuration de l'interface. Tout le code placé après elle ne sera pris en compte que lors de la sortie de l'interface via l'appel $mw- >destroy(9).

Si l'on oublie d'inclure l'instruction MainLoop, le programme semblera « réfléchir » pendant un moment, puis reviendra à l'invite de l'interpréteur de commande. Aucune fenêtre, aucun bouton ou widget ne sera tracé. L'une des premières choses qui se passent après l'appel à MainLoop est le dessin de l'interface et le lancement de la boucle principale.

Avant d'aller plus loin dans la boucle d'événement et dans ce qu'elle fait (et dans ce que vous devez faire pour qu'elle fonctionne correctement), examinons un programme réel en fonctionnement, « Bonjour tout le monde » (vous attendiez autre chose ?).

I-K. Un exemple : « Bonjour tout le monde »

Tout langage de programmation passe par l'exemple « Bonjour tout le monde ». C'est un bon exemple car il montre comment faire quelque chose de simple mais utile. Dans cet exemple, le titre de notre fenêtre affiche « Bonjour tout le monde » et nous utilisons un bouton permettant de quitter l'application :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
$mw->title("Bonjour tout le monde");
$mw->Button(-text => "Fin", -command => sub { exit; })->pack;
MainLoop;

Bien qu'il ne fasse que six lignes, il se passe un certain nombre de choses dans notre petit programme. La première ligne, comme tout programmeur Perl le sait, appelle Perl (uniquement sous Unix ; avec Win32, vous devez taper perl hello.pI pour l'invoquer). La deuxième indique à Perl que nous souhaitons utiliser le module Tk.

La troisième ligne

 
Sélectionnez
my $mw = MainWindow->new;

crée une fenêtre. Elle aura les mêmes attributs de base du gestionnaire de fenêtres que toutes vos autres fenêtres. Que ce soit dans un environnement Unix ou Windows, elle ressemblera à n'importe quelle autre fenêtre.

Son titre est modifié en utilisant la méthode title. Si l'on n'avait pas utilisé cette méthode, le texte apparaissant sur la barre de titre serait le même que le nom du fichier contenant le code. Ainsi, si notre script était stocké dans un fichier nommé bonjour, la chaîne « Bonjour » s'inscrirait dans la barre de titre de notre application (Tk met automatiquement la première lettre en majuscule). On n'est pas obligé d'utiliser la méthode title mais elle donne à l'application un aspect plus fini.

Toute chaîne passée en paramètre devient le titre de la fenêtre. Si l'on voulait que le titre soit « Hé ! Visez mon super programme! », ce serait là qu'il faudrait le préciser. Cela ressemble à l'utilisation de l'option -title au lancement de n'importe quelle application X standard. Il existe encore d'autres méthodes pour les objets MainWindow ; nous les traiterons plus tard, aux chapitres 12 et 13.

La ligne suivante crée un widget Button, configure ses propriétés de base, et le place (voir le chapitre 3, Le bouton de base, pour connaître toutes les options de configuration possibles).

Le bouton est configuré pour afficher le texte « Fin » puis appeler la fonction exit de Perl lorsqu'il est pressé. Enfin, la dernière ligne est l'appel de la fonction MainLoop. Celle-ci met en marche le gestionnaire d'événements et, à partir de là, l'application ne fera que ce qu'on lui a demandé de faire : si l'utilisateur clique sur le bouton, elle se terminera. Tout ce que l'utilisateur fait d'autre – mise en icône, modification de la taille, passer à une autre application – sera traité par le gestionnaire de fenêtres et ignoré par notre application. La figure 1.1 représente un affichage possible de la fenêtre « Bonjour tout le monde ».

Image non disponible
Figure 1.1 : Fenêtre « Bonjour tout le monde »

I-L. Utilisation de exit ou de destroy

Dans tous les exemples de ce livre, on utilise sub { exit; } pour quitter une application Perl/Tk. Cela fonctionne bien tant que vous employez use Tk; dans le fichier contenant le sub { exit; }. Perl/Tk définit sa propre fonction exit, qui réalise certaines tâches de nettoyage et autres choses diverses et importantes pour lui. Une autre façon de quitter la partie Tk de l'application est d'appeler $mw->destroy(), qui détruit la fenêtre principale et passe au code situé après l'instruction MainLoop. Ce code ne sera pas exécuté si l'on utilise sub { exit; }. Gardez cela à l'esprit si vous comptez faire quelque chose après la fin de la partie interface.

I-M. Conventions pour les noms des widgets

Des conventions pour les noms ? Qu'est-ce que cela peut être ennuyeux ! En fait, nos programmes deviennent parfois si gros et difficiles à manier que l'on ne peut mémoriser ce que désigne cette fichue variable $bouton. Si notre programme comprenait plus de dix boutons, ce serait plutôt difficile de se rappeler auquel correspond $bouton3 sans devoir se plonger dans un paquet de lignes de code.

Je suggère simplement une convention de nommage et, si elle vous plaît, utilisez-la ! Sinon, utilisez la vôtre ou priez pour avoir une très bonne mémoire.

Pour les boutons, j'aime bien utiliser b_, btn_ ou Bouton pour qualifier le nom de la variable. Ainsi, j'appellerai mon bouton de l'exemple « Bonjour tout le monde » $b_fin, $btn_fin ou $BoutonFin.

Un widget spécial est la première fenêtre que nous créons avec la méthode MainWindow. J'utilise toujours $mw comme nom de variable pour celle-ci. Vous verrez d'autres programmes l'appeler $main ou $mainwindow.

Le tableau 1-1 contient une liste des types de widget et ce que je suggère comme noms pour chacun d'eux. Remplacez « truc » par quelque chose de plus descriptif (exit, par exemple). Si vous utilisez cette convention, vous saurez toujours avec quel type de widget vous êtes en train de travailler.

Tableau 1-1 : Conventions de noms par type de widget

Type de widget

Suggestions de noms

Exemples

Button

$b_truc (ou $btn_truc, $Bouton_Truc)

$b_fin, $b_appliquer, $BoutonNouveau

Canvas

$canevas_truc ou $Canevas-Truc

$canevas_principal, $CanevasPetit

Checkbutton

$cc_truc ou $CaseCocherTruc

$cc_majuscule, $CaseCocherMinuscule

Entry

$s_truc ou $SaisieTruc

$s_nom, $SaisieAdresse

Frame

$c_truc ou $CadreTruc

$c_principal, $c_gauche, $CadreCanevas

Label

$e_truc ou $EtiquetteTruc

$e_nom, $EtiquetteAdresse

Listbox

$bl_truc ou $BoiteListeTruc

$bl_equipes, $BoiteListeEquipes

Menu

$m_truc ou $Menu_Truc

$m_fichier, $m_editer, $MenuAide

Radiobutton

$br_truc ou $BoutonRadio-Truc

$br_bleu, $br_gris, $BoutonRadioRouge

Scale

$curseur_truc ou $CurseurTruc

$curseur_age, $CurseurRevenus

Scrollbar

$defil_truc ou $DefilTruc

$defil_x, $DefilY

Text

$t_truc (ou $txt_truc) ou $TexteTruc

$txt_fichier, $TexteCommentaire

Toplevel

$f_truc ou $FenetreTruc

$f_principale, $FenetreOuvrirFichier

J'avoue ne pas toujours respecter mes propres règles. Tout au long de ce livre, vous me verrez simplement utiliser $bouton dans les exemples de code. J'utiliserai $bouton1 et $bouton2 s'il y en a deux dans l'exemple. Dans tout ce qui dépasse quelques lignes, j'essaierai (parole de scout ?) de respecter ma convention : j'utiliserai toujours un nom indiquant le type du widget auquel je fais référence.

I-N. Utilisation de print pour les diagnostics et les recherches d'erreur

Normalement, vous lancerez vos programmes Perl/Tk en tapant le nom du programme à l'invite de l'interpréteur de commande :

 
Sélectionnez
% bonjour

ou

 
Sélectionnez
C:\> perl bonjour

Quand vous invoquez ainsi le programme, toute sortie produite par une instruction print (ou printf) est envoyée à cette fenêtre du terminal. Parfois, vous ne verrez pas l'information réellement affichée tant que vous n'aurez pas quitté l'application. C'est probablement dû au fait que vous avez oublié de placer un \n à la fin de la chaîne à afficher, qui provoque un vidage automatique du tampon de sortie. Pendant l'exécution de votre application, si vous pensez que vous ne voyez pas apparaître le résultat d'une instruction print alors que cela devrait être le cas, assurez-vous que ce print contient bien un \n.

I-O. Conception de vos fenêtres (une approche rapide)

Avant de décider quels sont les événements à gérer, cela vaut la peine de passer un peu de temps à esquisser quelques fenêtres sur papier et de décider ce qui devrait se passer (du point de vue de l'utilisateur) lorsque l'on clique sur un bouton ou que l'on choisit une option d'un menu.

L'une des choses les plus importantes à mémoriser lorsque l'on conçoit les fenêtres de ses applications est que rien ne se passe tant que l'on n'est pas entré dans la boucle d'événement. Tout ce qui précède l'appel à MainLoop ne sert qu'à préparer cette boucle.

Une interface utilisateur graphique donne souvent à une application un aspect plus achevé et plus complet que ne le ferait une interface en ligne de commande. De plus, avec un GUI, il est souvent plus facile de manipuler de nombreux types différents d'entrées utilisateur.

Voici certains points à considérer lorsque vous décidez de l'aspect de l'interface graphique :

  • chaque widget doit avoir un rôle. Il doit être intuitif et donner des informations ;
  • pensez à la façon dont un utilisateur se servira d'une application, et concevez-la en fonction de cela ;
  • n'essayez pas de fourrer tout ce que fait l'application dans une seule fenêtre ;
  • n'essayez pas de toujours tout séparer en plusieurs fenêtres. Parfois, une application est si simple qu'une seule fenêtre suffit ;
  • les couleurs c'est bien, mais il existe beaucoup de personnes insensibles aux couleurs autour de vous. Si vous tenez tant à utiliser des couleurs, faites en sorte qu'elles soient personnalisables via un fichier ou par l'application elle-même ;
  • certains widgets font mieux leur travail que d'autres. Utilisez le widget qui convient le mieux à ce que vous voulez faire.

C'est tout pour la lecture. Maintenant, préparez-vous à apprendre les ficelles.


précédentsommairesuivant
Sauf si vous utilisez la distribution binaire pour Win32 de CPAN. Si vous avez installé la dernière distribution Perl d'ActiveState, vous devrez ensuite vous connecter à l'Internet pour installer le module Tk en utilisant PPM et en tapant INSTALL TK.
NDT Tous les exemples de cette traduction ont été testés et fonctionnent parfaitement sous Unix avec Tk800.008.
NDT Il est d'usage, lorsque l'on apprend un nouveau langage de programmation, de créer un premier programme affichant simplement « Bonjour tout le monde » (ou Hello, world!, en anglais).
Si vous avez installé la dernière distribution Perl d'ActiveState, vous devrez ensuite vous connecter à l'Internet pour installer le module Tk en utilisant PPM et en tapant INSTALL TK.
Sous Windows, utilisez la syntaxe Perl -e "use Tk".
NDT Pour des raisons de lisibilité, ce message a été découpé en plusieurs lignes.
NDT Si vous utilisez la version GNU de tar, vous pouvez regrouper les deux dernières commandes en une seule : tar -xvzf.
Tout au long de ce livre, j'utiliserai $mw pour indiquer la variable désignant la fenêtre principale créée au début de l'application (main window en anglais, d'où l'acronyme que nous conserverons dans cette traduction).

Licence Creative Commons
Le contenu de cet article est rédigé par Nancy Walsh et est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Pas de Modification 3.0 non transposé.
Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright © 2018 Developpez.com.