Introduction à Perl/Tk

Interfaces graphiques avec Perl


précédentsommairesuivant

III. Le bouton de base

III-A. Le widget Button

De tous les widgets disponibles en Perl/Tk, le bouton est l'un des plus souvent utilisés : il n'est qu'à voir tous les exemples du chapitre 2, Gestion de l'espace. Lorsqu'un bouton est pressé, quelque chose se passe. Cela peut aller de la sortie du programme (comme dans notre exemple « Bonjour tout le monde »), au début d'une longue suite d'opérations, comme l'ouverture d'un fichier ou le lancement d'un autre processus. Typiquement, un bouton affiche un texte court : Terminé, Appliquer, Sauver, OK, Fin.

D'autres widgets sont aussi considérés comme des boutons : les boutons radio, les cases à cocher et les boutons de menu. Ce chapitre traite des boutons traditionnels. Le chapitre 4, Cases à cocher et boutons radio, et le chapitre 11, Menus, traiteront des autres types, car ils ne se présentent pas de la même façon à l'écran et se comportent différemment.

Nous traitons d'abord du widget bouton, car il est facile de constater comment les différentes options affectent sa présentation. La plupart des autres widgets de Perl/Tk utilisent les mêmes options. Normalement, si un nom d'option est le même, la modification que celle-ci apportera au widget sera aussi (plus ou moins) la même.

III-A-1. Création d'un bouton

On utilise la syntaxe suivante pour créer un bouton :

 
Sélectionnez
$bouton = $widget_parent->Button( [ option => valeur, ... ] ) ;

Nous avons déjà vu des exemples de boutons dans notre programme « Bonjour tout le monde » du chapitre 1, ainsi que dans tous les exemples de gestion de l'espace du chapitre 2. Dans ceux-ci, un bouton est créé et placé sur l'écran avec une instruction comme :

 
Sélectionnez
$mw->Button(-text => "Terminé", -command => sub { exit })->pack;

Vous pouvez faire en sorte de conserver une référence au bouton de la façon suivante :

 
Sélectionnez
$bouton = $mw->Button(-text => "Terminé", -command => sub { exit })->pack;

Dans « Bonjour tout le monde », nous n'avions pas besoin de faire ensuite référence au bouton et cela n'aurait donc pas eu d'intérêt d'en conserver une. Cependant, dans la plupart des exemples de ce chapitre, nous supposerons que nous avons sauvegardé une référence au widget bouton au moment de sa création.

III-A-2. Options d'un bouton standard

Le reste de ce chapitre traite des options vous permettant de changer l'aspect du bouton et de lui faire faire ce que vous voulez.

-activebackground => couleur

  • Configure la couleur que devra prendre le fond lorsque le curseur de la souris est au-dessus du bouton. Une couleur est exprimée sous la forme d'une chaîne : "red", par exemple.

-activeforeground => couleur

  • Configure la couleur que devra prendre le texte lorsque le curseur de la souris est au-dessus du bouton.

-anchor => 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' |'nw' | 'center'

  • Permet d'ancrer le texte à la position spécifiée du bouton.

-background => couleur

  • Configure la couleur de fond du bouton.

-bitmap => nom_bitmap

  • Précise le bitmap par défaut, ou l'emplacement d'un fichier bitmap (avec @ devant son chemin d'accès).

-borderwidth => montant

  • Change la largeur du bord tracé autour du bouton (met en évidence l'option -relief).

-command => fct_rappel

  • Donne un pointeur vers une fonction qui sera appelée lorsque le bouton sera pressé.

-cursor => nom_curseur

  • Indique que le curseur de la souris se changera en nom_curseur lorsqu'il sera au-dessus du bouton.

-disabledforeground => couleur

  • Configure la couleur que devra prendre le texte lorsque le bouton sera désactivé.

-font => nom_fonte

  • Change la fonte de tout le texte du bouton.

-foreground => couleur

  • Change la couleur du texte en couleur.

-height => montant

  • Configure la hauteur du bouton : en caractères si du texte y est affiché, ou en distances d'écran s'il contient une image ou un bitmap.

-highlightbackground => couleur

  • Configure la couleur de la zone derrière le rectangle de focus (qui apparaît lorsque le widget n'a pas le focus).

-highlightcolor => couleur

  • Configure la couleur du rectangle de focus (qui apparaît lorsque le widget a le focus).

-highlightthickness => montant

  • Configure l'épaisseur de la boîte noire située autour du bouton ; indiquant qu'il a le focus.

-image => ptr_img

  • ptr_img est un pointeur vers un objet Image, créé à partir d'un fichier GIF ou PPM/PGM .

-justify => 'left' | 'right' | 'center'

  • Indique le bord du bouton contre lequel s'alignera un texte de plusieurs lignes.

-padx => montant

  • Ajoute des espaces à gauche et à droite, à l'intérieur du contour du bouton.

-pady => montant

  • Ajoute des espaces au-dessus et en dessous, à l'intérieur du contour du bouton.

-relief => 'flat' | 'groove' | 'raised' | 'ridge' | 'sunken' | 'solid'

  • Modifie le type du contour tracé autour du bouton.

-state => 'normal' | 'disabled' | 'active'

  • Indique l'état de réactivité du bouton. Si cette option vaut "disabled" , le bouton ne répondra pas.

-takefocus => 0 | 1 | undef

  • Indique que le bouton n'obtiendra jamais le focus (0), l'obtiendra toujours (1), ou laisse l'application décider (undef).

-text => texte

  • Indique le texte affiché dans le bouton.

-textvariable => \$variable

  • Pointeur vers une variable contenant le texte à afficher dans le bouton. Ce texte changera en même temps que ce que contient $variable.

-underline => n

  • Souligne le nième caractère du texte. Permet d'utiliser ce caractère au clavier pour cliquer lorsque le bouton a le focus.

-width => montant

  • Configure la largeur du bouton : en caractères si du texte y est affiché, ou en distances d'écran s'il contient une image ou un bitmap.

-wraplength => montant

  • Configure, en distances d'écran, le montant maximal de texte affiché sur une seule ligne. Cette option vaut 0 par défaut.

III-A-3. Affichage de texte

Pour que l'utilisateur sache ce que fait le bouton lorsqu'il est pressé, on doit indiquer le rôle de ce bouton à l'aide d'un texte. L'option réalisant cette opération est -text :

 
Sélectionnez
-text => 'texte'

Au moment de décider du texte descriptif, préférez un commentaire simple et court si vous ne souhaitez pas que le bouton occupe toute la fenêtre à cause d'un texte trop long.

Le texte peut contenir n'importe quoi : des caractères alphanumériques, un ou plusieurs retours à la ligne, des variables. Si elle est mise entre apostrophes simples, la chaîne sera interprétée littéralement ; entre apostrophes doubles, elle sera interpolée, exactement comme n'importe quelle chaîne en Perl. L'interpolation n'a lieu qu'une seule fois (la première fois que l'option est analysée). Si la variable est modifiée plus tard dans le programme, cela n'aura pas d'effet sur le texte du bouton. La seule façon de changer la chaîne après la création est d'utiliser la méthode configure pour la modifier (en faisant, par exemple, $bouton->configure(-text => "nouveau texte");) ou d'utiliser l'option -textvariable.

L'option -text n'a pas de valeur par défaut ; le bouton n'aura simplement pas de texte si vous ne spécifiez pas de valeur pour cette option.

L'autre moyen d'afficher du texte sur le bouton est d'utiliser l'option -textvariable. Celle-ci permet d'associer une variable scalaire au bouton ; le contenu de cette variable y sera affiché. On la spécifie de la façon suivante :

 
Sélectionnez
-textvariable => \$variable

L'utilisation de cette option implique que le texte du bouton changera en même temps que le contenu de $variable. Lorsque le texte change, le bouton ajuste sa taille à celui-ci, et la taille de la fenêtre entière peut donc être modifiée.

Ce morceau de code montre comment utiliser l'option -textvariable :

 
Sélectionnez
$cpteur = 0;
$mw->Button(
    -text    => "+ 1",
    -command => sub { $cpteur++ }
)->pack( -side => 'left' );
$mw->Button( -textvariable => \$cpteur )->pack( -side => 'left' );
$mw->Button(
    -text    => "Fin",
    -command => sub { exit }
)->pack( -side => 'left' );

La figure 3.1 montre deux fenêtres : la première représente la fenêtre juste après sa création, la deuxième, la même fenêtre après avoir cliqué vingt fois sur le bouton « + 1 ».

Image non disponible
Figure 3.1 : Exemple d'utilisation de l'option -textvariable

III-A-4. Afficher une image ou un bitmap à la place du texte

Au lieu d'afficher une chaîne sur le bouton, on peut utiliser l'option -image pour afficher une image.

 
Sélectionnez
-image => $ptr_img

Les formats d'images admis sont GIF et PPM/PGM. Les images JPEG sont reconnues en utilisant un module séparé (Tk::JPEG), disponible sur CPAN. D'autres types d'images sont également reconnus à mesure que de nouveaux modules comme Tk::JPEG sont développés. Vérifiez ceux qui sont actuellement disponibles sur CPAN.

Lorsque l'on utilise une image, seule celle-ci sera affichée, car le bouton ne peut afficher qu'une chaîne de texte ou une image, pas les deux. Pour créer une variable $ptr_img, on utilise la méthode Photo (en lui fournissant le nom et le chemin de l'image si elle ne se trouve pas dans le répertoire courant). La variable $ptr_img est ensuite donnée comme valeur de l'option -image :

 
Sélectionnez
$image = $mw->Photo( -file => "Xcamel.gif" );
$mw->Button(
    -text    => 'Fin',
    -command => sub { exit },
    -image   => $image
)->pack;

La figure 3.2 montre un exemple de bouton contenant un fichier GIF(12).

Image non disponible
Figure 3.2 : Bouton contenant une image à la place du texte

Pour afficher un bitmap, on utilise l'option -bitmap et on fournit son nom :

 
Sélectionnez
-bitmap => 'nom_bitmap'

Il existe plusieurs bitmaps par défaut : error, gray12, gray25, gray50, gray75, hourglass, info, questhead, question, et warning (voir la figure 3.3). On les précise en donnant à l'option leur nom entre apostrophes :

 
Sélectionnez
$mw->Button(-bitmap => 'error', -command => \&gestion_erreur)->pack;

Pour utiliser un fichier bitmap, on doit placer un @ devant son nom complet :

 
Sélectionnez
$mw->Button(
    -bitmap  => '@/usr/share/bitmap/monbitmap', 
    -command => sub { exit }
)->pack;

Notez que, si vous utilisez des apostrophes doubles, il faut protéger le @ avec un antislash (ici, "\@/usr/share/bitmap/monbitmap").

Image non disponible
Figure 3.3 : Fenêtre affichant tous les bitmaps par défaut

III-A-5. Assignation d'une fonction de rappel

Tout comme l'option -text, l'option -command est quasiment toujours utilisée lors de la création d'un bouton. Pour que ce dernier fasse quelque chose lorsqu'il est pressé, il faut lui associer une fonction de rappel (callback) en utilisant l'option -command. Cette fonction sera exécutée lorsque le bouton 1 de la souris est pressé au-dessus du bouton(13). Si l'on clique sur le bouton, mais que l'on déplace le curseur à l'extérieur de celui-ci avant de le relâcher, rien ne se passera, car le clic souris aura été annulé.

Dans le programme « Bonjour tout le monde », nous avons utilisé la fonction exit comme fonction de rappel :

 
Sélectionnez
$mw->Button(-text => "Fin", -command => sub { exit })->pack;

Il y a plusieurs façons d'associer une fonction, ou un ensemble d'instructions, à un bouton. Ce qui suit s'applique à tous les widgets disposant d'une option -command, vous la verrez donc souvent revenir.

III-A-6. Définition d'une fonction de rappel

Une fonction de rappel peut être définie de plusieurs façons :

  • comme une fonction anonyme : par exemple, sub { faire quelque chose } ;
  • comme une référence à une fonction : par exemple, \&mafonction ;
  • comme une liste anonyme dont le premier élément est une référence à une fonction, et les autres les paramètres passés à cette fonction :
 
Sélectionnez
[ \&mafonction, $arg0, $arg1, \@arg2...].

Le bouton créé dans notre programme « Bonjour tout le monde » utilisait une fonction anonyme. Voici à nouveau le code :

 
Sélectionnez
$mw->Button(-text => "Fin", -command => sub { exit; })->pack;

Nous aurions aussi pu créer la fonction anonyme avant de créer le bouton et lui passer la référence à celle-ci :

 
Sélectionnez
$ref_fonction = sub { exit }; 
$mw->Button(-text => "Fin", -command => $ref_fonction)->pack;

C'est utile dans le cas où notre fonction anonyme réalise plusieurs choses et que cela serait affreux de la mettre dans la liste des paramètres du bouton.

Nous aurions aussi pu créer une fonction classique pour gérer le exit, puis passer une référence à celle-ci :

 
Sélectionnez
sub sortir { 
    &faire_autre_chose; 
    exit; 
} 
$mw->Button(-text => "Fin", -command => \&sortir )->pack;

Il est conseillé d'utiliser une fonction comme celle-ci si vous prévoyez plus d'une possibilité de quitter votre application. Vous pourriez, par exemple, configurer votre programme pour que l'on puisse en sortir via un menu, un bouton ou la commande Close du gestionnaire de fenêtres.

Si vous devez passer des paramètres à votre fonction exit, utilisez la forme de liste anonyme :

 
Sélectionnez
sub sortir { 
    my ($arg1, $arg2) = @_; 
    &faire_autre_chose if ($arg1 = 12); 
    exit; 
} 
$mw->Button(-text => "Fin", 
            -command => [ \&sortir, 12, 'ciao' ])->pack;

Il est important de se rappeler comment les différentes façons d'indiquer une fonction de rappel affectent la portée des variables.

III-A-7. Fonctions anonymes

Les fonctions anonymes sont « mises de côté » pour être appelées plus tard, à partir de la boucle des événements, MainLoop. Les commandes contenues dans la fonction ne seront pas analysées, et toutes les variables qu'elle utilise ne seront pas non plus évaluées tant que cette fonction n'est pas appelée.

 
Sélectionnez
foreach (@noms) {
    $mw->Button(
        -text    => $_,
        -command => sub { print "$_ a été pressé !\n"; }
    )->pack;
}

Le code précédent utilise la variable $_ dans la boucle foreach. Le texte du bouton vaudra ce qui est attendu, car $_ est évalué quand le bouton est créé. Cependant, le $_ dans la portée de la fonction anonyme ne sera pas évalué jusqu'à ce que le bouton soit vraiment pressé. À ce moment-là, $_ pourrait ne pas être défini et des erreurs commenceraient à s'afficher à chaque fois que vous cliqueriez sur le bouton.

Une référence à une fonction et une liste anonyme sont très similaires, hormis le fait que la liste permet de passer des paramètres supplémentaires à la fonction (notamment ceux dans la portée courante) :

 
Sélectionnez
foreach (@noms) {
    $mw->Button(
        -text    => $_,
        -command => [ \&affiche_nom, $_ ]
    )->pack;
}

sub affiche_nom {
    print "$_[0] a été pressé !\n";
}

La liste anonyme est créée pendant l'appel de création du bouton. Cela signifie que le $_ de cette liste est évalué dans le contexte de la boucle foreach et vaudra la même valeur que celle utilisée par l'option -text.

Ceux d'entre vous, qui ont l'habitude de créer des fonctions anonymes au vol, peuvent aussi faire la même chose de cette façon :

 
Sélectionnez
foreach (@noms) {
    $mw->Button(
        -text    => $_,
        -command => [ sub { print " $_[0] a été pressé !\n"; }, $_ ]
    )->pack;
}

La fonction anonyme est le premier élément de la liste de l'option -command, le second élément est le paramètre $_. Pensez au fait que vous voudrez parfois beaucoup plus qu'une simple instruction print dans votre fonction et que, pour des raisons de lisibilité, il est préférable de la placer dans une fonction.

Ce qui précède n'est qu'un survol rapide des fonctions anonymes et de leur fonctionnement avec Perl/Tk : le Camel Book(14) contient toutes les informations nécessaires, et plus encore.

III-A-8. Désactiver un bouton

Lorsqu'un bouton est créé, il se présente par défaut comme étant prêt à fonctionner. Il changera de couleur lorsque la souris passe au-dessus de lui et exécutera la fonction de rappel associée lorsqu'il est pressé. Vous pouvez changer cela à l'aide de l'option -state.

  • -state => "normal" | "disabled" | "active"

L'état "normal" vient juste d'être décrit. L'état "active" correspond au cas où le curseur de la souris se trouve au-dessus du bouton, il est utilisé de façon interne. L'état "disabled" fait que le bouton apparaîtra « grisé » (ou avec des couleurs spécifiées par les options -disabledforeground et -disabledbackground) et qu'il ne répondra à aucune action.

Un bouton ne devrait être sélectionnable que s'il sert à quelque chose dans l'application ; on peut, par exemple, envisager un bouton qui, une fois pressé, en désactiverait un autre.

Le code ressemblerait à :

 
Sélectionnez
my $b_fin = $mw->Button(
    -text    => 'Sortie',
    -command => sub { exit }
)->pack;
$var = "Empêcher la sortie";
$mw->Button(
    -textvariable => \$var,
    -command      => sub {
        my $etat = $b_fin->configure( -state );
        if ( $etat eq "disabled" ) {
            $b_fin->configure( -state => 'normal' );
            $var = "Empêcher la sortie";
        }
        else {
            $b_fin->configure( -state => 'disabled' );
            $var = "Autoriser la sortie";
        }
    }
)->pack;

Dans cet exemple, on sauvegarde une référence au bouton « Sortie », car on l'utilisera plus tard pour changer l'état de ce bouton. Notez aussi que $b_fln est utilisé en dehors de la portée de la fonction anonyme. Cela ne fonctionnera que si $b_fln reste dans la portée globale du programme afin que cette variable soit définie lorsque la fonction anonyme est exécutée. Faites attention à ne pas affecter autre chose à, $b_fln car, si vous le faites, la fonction anonyme, lorsqu'elle sera appelée fera référence à la nouvelle valeur de $b_fln, pas à celle que vous souhaitez.

La figure 3.4 montre la fenêtre après que l'on a cliqué une fois sur le bouton « Empêcher la sortie ».

Image non disponible
Figure 3.4 : Fenêtre avec un bouton désactivé (« Sortie ») et un bouton normal

La méthode configure est expliquée plus loin dans ce chapitre ; ne vous souciez pas de son fonctionnement pour l'instant.

Le fait de désactiver des widgets lorsqu'ils ne servent pas permet de donner des indications visuelles aux utilisateurs quant à ce qu'ils peuvent ou ne peuvent pas faire dans l'application.

III-A-9. Manipulation du texte

En plus d'afficher du texte sur le bouton, on peut modifier l'apparence et l'emplacement de ce texte dans le bouton. Pour ce faire, la façon la plus simple consiste à utiliser l'option -font afin de changer la fonte :

 
Sélectionnez
-font => 'nom_fonte'

Il y a plusieurs moyens de spécifier une fonte. Si vous utilisez Tk4 (qui est la version courante au moment où ce livre est écrit), suivez les instructions des paragraphes suivants. Si vous utilisez la dernière version de Perl/Tk, qui utilise Tk8.0(15), lisez l'annexe C, Fontes : elle présente les nouvelles méthodes à utiliser avec les fontes.

La nouvelle fonte est indiquée sous la forme d'une chaîne contenant son nom. Il y a une différence entre les façons d'indiquer les fontes pour des systèmes Win32 et pour des systèmes Unix. Les fontes disponibles sous votre système X Window peuvent être connues grâce à la commande xlsfonts ou en utilisant le module Tk::Fonts. La fonte par défaut pour le widget bouton, sur mon système Unix est(16) :

 
Sélectionnez
"-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*"

Bien que vous verrez cette fonte par défaut sur un système Win32, vous devrez passer un autre type de chaîne comme valeur de l'option -font. Voici un exemple :

 
Sélectionnez
-font => "{Times New Roman} 12 {normal}"

Vous pouvez aller voir dans le Panneau de configuration de Windows 95/NT, sous la rubrique « Fontes » pour connaître les fontes disponibles. Si vous double-cliquez sur une fonte, une fenêtre s'ouvrira et affichera celle-ci dans ses différentes tailles disponibles. Utilisez le nom tel qu'il est mentionné dans le répertoire Fonts pour former la première partie du nom entre accolades. Le nombre qui suit est la taille de la fonte en points. La troisième partie est son type, habituellement il s'agit de normal, italiques, ou gras.

Il ne peut y avoir qu'une fonte par bouton et le texte ne peut donc pas en changer au milieu d'un mot, mais chaque bouton (ou widget) d'une application peut utiliser une fonte différente. Voici un exemple de deux boutons dans une même fenêtre, l'un utilise la fonte par défaut, l'autre « lucidasans-14 » (une fonte Unix) :

 
Sélectionnez
$mw->Button(
    -text    => "Fin",
    -command => sub { exit }
)->pack(
    -side   => 'left',
    -fill   => 'both',
    -expand => 1
);
$mw->Button(
    -text    => "Fin",
    -font    => "lucidasans-14",
    -command => sub { exit }
)->pack(
    -side   => 'left',
    -fill   => 'both',
    -expand => 1
);

La figure 3.5 montre le résultat :

Image non disponible
Figure 3.5 : Boutons avec des fontes différentes

En plus de modifier la fonte, on peut aussi déplacer le texte dans le bouton. On peut changer la position par rapport à laquelle le texte s'alignera de lui-même, comme avec un traitement de texte, grâce à l'option -justify :

  • -justify => 'left' | 'right' | 'center'

La valeur par défaut de -justify est 'center'. Normalement, le texte affiché dans un bouton est un texte court d'un ou deux mots : « Fin », « Terminé », « Oui », « Non » ou « Annuler », par exemple. L'alignement du texte ne saute pas aux yeux, sauf lorsqu'il s'étale sur plusieurs lignes et, par défaut, le bouton n'affichera plusieurs lignes que si la chaîne contient un caractère \n. On peut aider le programme à décider où couper les lignes en utilisant l'option -wraplength :

 
Sélectionnez
-wraplength => 'longueurmax'

'longueurmax' indique la longueur maximale de la ligne en distances d'écran (voir le chapitre 2). Si la longueur du texte du bouton excède ce montant, le texte sera coupé et ira à la ligne. La valeur par défaut de -wraplength est 0.

Voici un exemple utilisant les deux options, -justify et -wraplength :

 
Sélectionnez
foreach (qw(left center right)) {
    $b = $mw->Button(
        -text       => "Ce bouton est aligné avec $_",
        -command    => sub { exit },
        -wraplength => 53,
        -justify    => $_
    )->pack(
        -side   => 'left',
        -fill   => 'both',
        -expand => 1
    );
}

La figure 3.6 montre ce que donnent ces trois boutons. Bien que cet exemple ne le montre pas, il est possible de couper le texte au milieu d'un mot.

Le dernier ajustement possible du texte (ou du bitmap) est celui de sa position dans le bouton. Celle-ci est contrôlée par l'option -anchor, qui fonctionne comme l'option -anchor des gestionnaires d'espace :

Image non disponible
Figure 3.6 : Effets des options -justify et -wraplength dans un bouton
  • -anchor => 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw' | 'center'

Tout comme une fenêtre, un bouton a des points cardinaux définissant des emplacements dans celui-ci. La figure 3.7 montre ces différents points.

Image non disponible
Figure 3.7 : Points d'ancrage dans un bouton

La position par défaut du texte est 'center'. Lorsque la position est modifiée, l'effet de cette option n'apparaît pas évident, sauf si le bouton s'agrandit. Dans la figure 3.8, le bouton est celui qui a été créé dans l'exemple sur l'option -justify (figure 3.6) sauf que -anchor => 'nw' a été ajouté à la liste de ses options.

Image non disponible
Figure 3.8 : L'ancre du bouton est positionnée à 'nw'

Comme cela a été évoqué plus haut, cette option est similaire à l'option -anchor de la méthode pack. Il est important de noter que cette option modifie la position du texte dans le bouton ; celle de pack modifie la position du widget dans la fenêtre.

III-A-10. Modification du style d'un bouton

Par défaut, un bouton se présente comme s'il était légèrement surélevé par rapport à la surface de la fenêtre. En utilisant l'option -relief, on peut modifier le style des bords du bouton :

  • -relief => 'flat' | 'groove' | 'raised' | 'ridge' | 'sunken' | 'solid'

Chaque valeur modifie légèrement l'aspect du bouton, comme vous pouvez le constater avec la figure 3.9.

flat

  • Le bouton apparaît comme s'il n'y avait que du texte dans la fenêtre. L'utilisation de 'flat' (qui signifie « plat », en français) n'est pas conseillée pour les boutons, car l'utilisateur n'a aucune information visuelle et ne peut savoir que le bouton peut être pressé (il ressemble à une étiquette).

groove

  • Donne un aspect légèrement enfoncé (groove signifie « rainure », en français) aux bords du bouton (comme s'il y avait un fossé autour du texte).

raised

  • C'est la valeur par défaut (« surélevé », en français) ; elle donne un aspect 3D avec une ombre sur les bords inférieur et droit, ce qui fait apparaître le bouton plus haut que la surface de la fenêtre.

ridge

  • L'opposé de groove (ridge signifie « ride ») ; fait apparaître une ride autour du texte.

sunken

  • L'opposé de raised (sunken signifie « en contrebas ») ; donne un effet 3D au bouton, le faisant apparaître en dessous de la surface de la fenêtre.

solid

  • Le bouton est sur le même plan que la fenêtre (comme 'flat'), mais son contour est matérialisé par un trait plein.

Quelle que soit la valeur choisie pour l'option -relief, l'aspect du bouton sera celui de 'sunken' lorsqu'il est pressé.

Image non disponible
Figure 3.9 : Les différents types de relief d'un bouton

En plus de changer le type des bords tracés autour d'un bouton, on peut aussi modifier l'épaisseur de ces bords avec l'option -borderwidth :

 
Sélectionnez
-borderwidth => montant

La valeur par défaut de -borderwidth est 2. Plus les bords sont larges, plus les effets de l'option relief sont marqués. La figure 3.10 montre ce que donne un -borderwidth de 10 pour chaque type de relief.

Image non disponible
Figure 3.10 : Les différents reliefs avec l'option -borderwidth à 10

On peut aussi spécifier -borderwidth en utilisant l'abréviation -bd. Bien que cette dernière donne les mêmes résultats, l'utilisation de -borderwidth rend le code plus facile à relire. De plus, -bd n'est pas reconnue par tous les widgets et compter sur elle peut s'avérer dangereux.

Je ne conseille pas l'utilisation de valeurs supérieures à 4 pour -borderwidth, car cela rend les widgets vraiment laids. Dans tous les chapitres sur les widgets, il y aura une copie d'écran montrant les effets d'une valeur de -borderwidth plus grande pour chacune des valeurs possibles de relief. La meilleure utilisation de -borderwidth est de faire ressortir un widget par rapport aux autres durant la phase de développement (je l'utilise souvent avec des cadres pour matérialiser leurs emplacements, car, normalement, ils sont invisibles : voir le chapitre 12).

III-A-11. Changer la taille d'un bouton

Normalement, la taille d'un bouton est automatiquement déterminée par l'application et dépend du texte ou de l'image que ce bouton affiche. La largeur et la hauteur peuvent, toutefois, être précisées explicitement avec les options -width et/ou -height :

 
Sélectionnez
-width => x, -height => y

Les valeurs spécifiées par x et y diffèrent selon que le bouton affiche un bitmap/image ou un texte. Dans le premier cas, ces valeurs représentent des distances d'écran, dans le deuxième, elles indiquent des nombres de caractères.

L'exemple suivant a un bouton avec sa taille par défaut et un autre, tracé avec des valeurs de 10 pour les deux options -width et -height (il n'est pas nécessaire que les valeurs de ces deux options soient les mêmes, ni d'utiliser les deux) :

 
Sélectionnez
$mw->Button(
    -text    => "Fin",
    -command => sub { exit }
)->pack( -side => 'left' );
$mw->Button(
    -text    => "Fin",
    -width   => 10,
    -height  => 10,
    -command => sub { exit }
)->pack( -side => 'left' );

Dans la figure 3.11, le second bouton est bien plus haut qu'il n'est large, car les caractères du texte sont plus hauts que larges.

Image non disponible
Figure 3.11 : Bouton par défaut et avec -width => 10, -height => 10

La valeur spécifiée par -width et -height est un nombre de caractères, car le bouton affiche du texte. Lorsque ces options sont utilisées avec un bitmap, la valeur est exprimée en distances d'écran. Voici un exemple d'utilisation de -width et -height avec un bitmap :

 
Sélectionnez
$mw->Button(
    -bitmap  => 'error',
    -width   => 10,
    -height  => 10,
    -command => sub { exit }
)->pack( -side => 'left' );
$mw->Button(
    -bitmap  => 'error',
    -command => sub { exit }
)->pack( -side => 'left' );
$mw->Button(
    -bitmap  => 'error',
    -width   => 50,
    -height  => 50,
    -command => sub { exit }
)->pack( -side => 'left' );

Le premier bouton est créé en réduisant sa largeur et sa hauteur à 10 pixels. Le bouton du milieu a une taille normale et le troisième est créé avec une largeur et une hauteur de 50 pixels. La figure 3.12 montre le résultat obtenu.

Image non disponible
Figure 3.12 : Boutons affichant le même bitmap, avec des valeurs différentes de -width et -height

La valeur par défaut de -width et -height est 0, qui demande au programme de décider dynamiquement de la largeur et de la hauteur du bouton.

La largeur totale d'un bouton de texte est égale à la largeur du texte plus un montant de 2 x -padx. Sa hauteur est la hauteur du texte, plus 2 x -pady. La largeur et la hauteur d'un bouton avec bitmap sont égales à la largeur et la hauteur du bitmap. Toute option -padx ou -pady est ignorée lorsqu'un bitmap est affiché.

Une autre possibilité pour préciser explicitement une largeur ou une hauteur consiste à augmenter la taille du bouton en utilisant les options -padx et/ou -padx pour ajouter des espaces de remplissage entre le texte et les bords du bouton :

 
Sélectionnez
-padx => montant, -pady => montant

Le montant spécifié pour -padx est ajouté à gauche et à droite du texte du bouton. Celui spécifié pour -pady est ajouté au-dessus et en dessous du texte bouton. La figure 3.13 montre le résultat obtenu.

En utilisant ces options, vous demandez au bouton d'être plus grand qu'il ne le serait normalement, mais vous n'avez pas à vous demander s'il sera plus petit, comme c'est le cas lorsque l'on utilise -width et -height.

Image non disponible
Figure 3.13 : Exemples de boutons avec -padx => 20, -pady => 20

N'oubliez pas que -padx et -pady sont ignorées lorsqu'un bitmap est affiché.

III-A-12. Ajouter un raccourci clavier

Un bouton est normalement employé par l'utilisateur via un clic du bouton 1 de la souris lorsque le curseur se trouve au-dessus de lui. Il peut aussi être activé en pressant la touche de tabulation jusqu'à ce que le bouton reçoive le focus, puis en appuyant sur la barre d'espace. Les effets sont les mêmes : la fonction de rappel associée au bouton est appelée et la valeur de l'option -relief est temporairement modifiée. Le focus clavier est matérialisé par un fin rectangle noir, tracé autour du widget (voir la figure 3.20, plus loin dans ce chapitre).

Pour activer le bouton en utilisant une autre touche du clavier, on peut utiliser l'option -underline dans un bouton affichant du texte :

 
Sélectionnez
-underline => N

Cela soulignera le nième caractère de la chaîne, le premier ayant la position 0. Avec la chaîne « Quitter », underline => 0 soulignera le premier caractère, le « Q » (voir la figure 3.14).

La valeur par défaut de underline est -1, ce qui signifie qu'aucun caractère ne sera souligné dans la chaîne.

Image non disponible
Figure 3.14 : Exemple avec -underline => 0

III-A-13. Options de couleur

Les options -background, -foreground, -activebackground, -activeforeground, et -disabledforeground permettent de modifier les couleurs d'un bouton. Chacune d'elles a pour valeur une chaîne identifiant une couleur. Cette dernière peut être le nom de la couleur, comme "blue", ou une valeur hexadécimale, comme "#d9d9d9", dénotant aussi une couleur, mais de façon beaucoup plus sibylline.

Sous Win32, comme avec les systèmes Unix, vous pouvez exécuter le script de démonstration widget, livré avec le module Perl/Tk. Si le répertoire des binaires Perl se trouve dans la liste de vos chemins par défaut, il suffit de taper widget sur la ligne de commande DOS ou Unix. Dans la section consacrée aux boîtes de liste se trouve un exemple affichant les noms des couleurs. Vous pouvez double-cliquer sur les noms de cette liste pour constater les changements de couleur de l'application. Les valeurs admises pour le nom de la couleur sont énumérées dans le fichier rgb.txt sur votre système Unix. Normalement, ce fichier se trouve dans le répertoire des bibliothèques X11. Sur mon système Linux, il se trouve dans /usr/X11R6/lib/X11. Sous X Window, vous pouvez également utiliser les applications xcolors ou showrgb. Consultez les pages de manuel de ces commandes pour les utiliser au mieux.

Le répertoire de votre distribution Perl est également un bon endroit pour rechercher les noms de couleurs (et cela s'applique aussi à Win32). Recherchez le fichier xcolors.h : il s'agit d'un fichier texte contenant les valeurs et les noms RGB d'un bon nombre de couleurs. Sur ma machine Windows 95, ce fichier se trouve dans le répertoire C: \Perl\lib\site\Tk\ptk.

La couleur d'un bouton dépend de son état courant. Lorsque celui-ci est 'normal', les couleurs affectées aux options -foreground et -background s'appliquent. Le fond du bouton est la zone située derrière la chaîne de texte, dans les limites du bouton ; sa couleur est indiquée de la façon suivante :

 
Sélectionnez
-background => couleur

La couleur par défaut du fond est gris clair ("#d9d9d9" en représentation RGB hexadécimale). La figure 3.15 montre ce que cela donne de colorer en bleu(17) le fond du second bouton « Fin ».

Image non disponible
Figure 3.15 : Exemple avec -background => 'blue'

Le premier plan d'un bouton est le texte (ou le bitmap) affiché. Sa couleur est précisée ainsi :

 
Sélectionnez
-foreground => couleur

Par défaut, -foreground vaut 'black'. Quelle que soit la couleur choisie, si vous voulez qu'elle soit visible, assurez-vous qu'elle soit assez contrastée par rapport à celle du fond. Dans l'exemple de la figure 3.15, la couleur du texte était celle par défaut et elle ne se détachait pas très bien de la couleur de fond du bouton. Si l'on met la valeur de -foreground à 'white', le texte sera bien plus lisible, comme vous pouvez le constater avec la figure 3.16. -fg est un raccourci pour -foreground qui peut ne pas fonctionner avec certains autres types de widgets. Pour cette raison, je vous conseille de conserver -foreground comme nom d'option.

Image non disponible
Figure 3.16 : Exemple avec -background => 'blue' et -foreground => 'white'

Lorsque l'on utilise les options -foreground et -background avec un bitmap, le premier plan et le fond de celui-ci seront des couleurs spécifiées. Les effets de ces couleurs dépendent du bitmap. Un exemple est donné à la figure 3.17.

Image non disponible
Figure 3.17 : Bitmap 'error' avec -foreground => 'white' et -background => 'black'

Les options -foreground et -background contrôlent les couleurs du bouton lorsqu'il est dans un état 'normal'. Lorsque le curseur de la souris est au-dessus de lui, les couleurs -activeforeground et -activebackground sont utilisées.

 
Sélectionnez
-activebackground => couleur, -activeforeground => couleur

Ces couleurs sont différentes, car nous voulons que l'utilisateur puisse se rendre compte qu'il peut presser le bouton. En faisant légèrement varier les couleurs lorsque le curseur de la souris passe au-dessus du bouton, il sait qu'il peut cliquer dessus pour faire quelque chose. La valeur par défaut de -activebackground est un gris légèrement plus foncé ("#ececec").

La dernière option de couleur, -disabledforeground, est la couleur du texte lorsque l'état du bouton est 'disabled'.

 
Sélectionnez
-disabledforeground => couleur

Lorsque le bouton est désactivé, il ne répondra pas lorsque le curseur de la souris se trouve au-dessus de lui, ou lorsqu'il est pressé. La couleur par défaut du texte (ou du bitmap) est "#a3a3a3". La figure 3.18 montre la différence entre les couleurs du texte d'un bouton désactivé et d'un bouton normal (nous avons déjà vu cet exemple avec la figure 3.4, retournez voir le code ayant permis de créer cette fenêtre).

Image non disponible
Figure 3.18 : Exemple avec -disabledforeground

III-A-14. Modification du curseur de la souris

Le curseur de la souris ressemble normalement à une flèche(18). Il peut être modifié pour chaque widget avec l'option -cursor :

 
Sélectionnez
-cursor => nom_curseur

Lorsque la souris est au-dessus du bouton, le curseur changera pour prendre l'aspect spécifié. Cette modification aura lieu, que le bouton soit désactivé ou non. Voici une liste de l'ensemble des curseurs disponibles.

X_cursor

arrow

based_arrow_down

based_arrow_up

boat

bogosity

bottom_left_corner

bottom_right_corner

bottom_side

bottom_tee

box_spiral

center_ptr

circle

clock

coffee_mug

cross

cross_reverse

crosshair

diamond_cross

dot

dotbox

double_arrow

draft_large

draft_small

draped_box

exchange

fleur

gobbler

gumby

hand1

hand2

heart

icon

iron_cross

left_ptr

left_side

left_tee

leftbutton

ll_angle

lr_angle

man

middlebutton

mouse

pencil

pirate

plus

question_arrow

right_ptr

right_side

right_tee

rightbutton

rtl_logo

sailboat

sb_down_arrow

sb_h_double_arrow

sb_left_arrow

sb_right_arrow

sb_up_arrow

sb_v_double_arrow

shuttle

sizing

spider

spraycan

star

target

tcross

top_left_arrow

top_left_corner

top_right_corner

top_side

top_tee

trek

ul_angle

umbrella

ur_angle

watch

xterm

     

Voici un programme interactif permettant de visualiser les différents curseurs :

Image non disponible
Figure 3.19 : Les curseurs standards
 
Sélectionnez
#!/usr/bin/perl -w
use Tk;

## Crée les éléments de la fenêtre
$mw = MainWindow->new;
$mw->Button(
    -text    => "Fin",
    -command => sub { exit }
)->pack(
    -side => "bottom",
    -fill => "x"
);
$defilement = $mw->Scrollbar;
$liste      = $mw->Listbox(
    -selectmode     => 'single',
    -yscrollcommand => [ set => $defilement ]
);

$defilement->configure( -command => [ yview => $liste ] );

$defilement->pack( -side => 'right', -fill => 'y' );
$liste->pack( -side => 'left', -fill => 'both' );

## Ouvre le fichier contenant tous les curseurs disponibles
## Vous pouvez devoir le modifier si votre cursorfont.h est ailleurs
## Sur les systèmes Win32, recherchez C:\Perl\lib\site\Tk\X11\cursorfont.h
open( CURSEURS, "/usr/X11R6/include/X11/cursorfont.h" )
  || die "Impossible d'ouvrir le fichier des curseurs.\n";

while (<CURSEURS>) {
    push( @curseurs, $1 ) if (/\#define XC_(\w+) /);
}

close(CURSEURS);

$liste->insert( 'end', sort @curseurs );
$liste->bind(
    '<Button-1>',
    sub {
        $mw->configure( -cursor => $liste->get( $liste->curselection ) );
    }
);

MainLoop;

Bien que ce programme puisse sembler un peu compliqué à ce moment du livre, regardez comment il fonctionne. Si vous ne comprenez pas tout tout de suite, c'est normal. Continuez à lire quelques chapitres et revenez le consulter jusqu'à ce que vous le compreniez. Les boîtes de liste sont traitées au chapitre 7, Le widget boîte de liste, et bind est expliquée au chapitre 14, Liaisons d'événements.

III-A-15. Options du focus

On peut tabuler entre les widgets d'une application pour les rendre accessibles à des entrées effectuées via le clavier. L'application indique qu'un widget est disponible pour une saisie au clavier en traçant autour de lui une bordure noire, appelée « rectangle de focus » (highlight rectangle, en anglais), comme montré par la figure 3.20. Si un widget est entouré de cette bordure, on dit qu'il a le focus de l'application (on peut forcer une application à donner le focus à un widget spécifique lorsqu'elle démarre en faisant $widget->focus;). Lorsqu'un bouton a le focus, on peut le presser avec la barre d'espace du clavier au lieu d'utiliser la souris.

Image non disponible
Figure 3.20 : Le premier bouton a le focus d'entrée

On peut faire en sorte que l'application empêche un bouton de recevoir le focus clavier à l'aide de l'option -takefocus :

  • -takefocus => 0 | 1 | undef

L'option -takefocus vaut normalement la chaîne vide (undef), ce qui permet à l'application de décider dynamiquement si le widget acceptera le focus ou non. Si un widget est dans l'état 'disabled', il sera ignoré lors des tabulations de widget en widget. Pour qu'une application ignore toujours le widget lors de ces tabulations, on utilise -takefocus => 0. Pour qu'elle autorise toujours le focus pour celui-ci, on utilise -takefocus => 1.

III-A-16. Modification du rectangle de focus

Le rectangle de focus(19) est normalement affiché avec une épaisseur de 2 pixels. On peut modifier cela en utilisant l'option -highlightthickness :

 
Sélectionnez
-highlightthickness => montant

Le montant spécifié est une distance d'écran quelconque. Le bouton « Fin », à droite de la figure 3.21, a -highlightthickness à 10 et possède le focus.

Image non disponible
Figure 3.21 : Exemple avec -highlightthickness => 10

Lorsqu'un bouton n'a pas le focus clavier, il est entouré d'un petit espace. Si cela vous ennuie, vous pouvez mettre -highlightthickness à 0, et cet espace ne s'affichera plus, même si ce widget a le focus. C'est une mauvaise façon de programmer que de mettre -highlightthickness à 0 si vous n'avez pas aussi mis -takefocus à 0.

La couleur du rectangle de focus peut également être modifiée. Pour ce faire, on utilise deux valeurs : la couleur du rectangle de focus lorsque le bouton le détient, et celle qu'il aura sinon. L'option -highlightcolor est la couleur que prend le rectangle de focus lorsque le bouton le détient :

 
Sélectionnez
-highlightcolor => couleur

La figure 3.22 montre le bouton droit avec le focus et -highlightcolor à 'yellow'. Comparez-la à la figure 3.21 pour constater la différence.

Image non disponible
Figure 3.22 : Exemple de bouton avec -highlightcolor => 'yellow'

Pour changer la couleur de l'espace autour du bouton lorsqu'il n'a pas le focus, on utilise l'option -highlightbackground :

 
Sélectionnez
-highlightbackground => couleur

Normalement, le rectangle de focus a la même couleur que le fond de la fenêtre, ce qui permet de le confondre avec le fond de la fenêtre ou du cadre contenant le bouton.

La figure 3.23 montre un exemple où les deux boutons ont la configuration suivante :

 
Sélectionnez
-highlightcolor => 'blue', -highlightbackground => 'yellow'

Le bouton de droite est celui qui possède le focus.

Image non disponible
Figure 3.23 : Boutons avec -highlightcolor => 'blue' et -highlightbackground => 'yellow'

III-A-17. Configuration d'un bouton

Après avoir créé le widget et sauvegardé une référence vers celui-ci dans un scalaire (comme $bouton), on peut appliquer des méthodes sur ce bouton.

Deux méthodes permettent de configurer un bouton après sa création et d'obtenir des informations sur sa configuration courante : configure et cget. Elles fonctionnent avec tous les widgets et sont décrites dans l'annexe A, Configuration des widgets avec configure et cget. Voici quelques exemples courants pour vous mettre sur les rails :

 
Sélectionnez
$etat = $bouton->cget( -state );         # Obtient la valeur courante de -state
$etat = $bouton->configure( -state );    # Obtient la valeur courante de -state
$bouton->configure( -text => "Nouveau texte" );    # Modifie le texte
$texte = $bouton->cget( -text );                   # Obtient la valeur courante de -text
@tout  = $bouton->configure();                     # Obtient des infos sur toutes
                                                   # les options du bouton

III-A-18. Clignotement d'un bouton

La méthode flash fait « clignoter » le bouton à l'écran. Il passe sans cesse de la couleur correspondant à l'état normal à la couleur correspondant à l'état actif, et réciproquement.

 
Sélectionnez
$bouton->flash();

III-A-19. Invocation d'un bouton

La méthode invoke appelle la fonction sur laquelle pointe l'option -command. Dès lors que vous avez utilisé -command pour assigner la fonction de rappel, vous pouvez utiliser invoke à chaque fois que vous avez besoin de réaliser la même opération :

 
Sélectionnez
$bouton->invoke();

III-B. Essayez et amusez-vous !

L'un des meilleurs moyens de comprendre comment fonctionne Perl/Tk est de l'essayer. Lorsque les bases ont été comprises, vous passerez le plus gros de votre temps à essayer les options et les fonctions de rappel pour obtenir les résultats voulus. Voici quelques voies à explorer pour mieux comprendre le widget bouton :

  • créez une fenêtre contenant trois boutons et faites en sorte que chaque bouton affiche quelque chose de différent lorsqu'il est cliqué ;
  • créez une fenêtre contenant trois boutons et faites en sorte que les deux premiers changent mutuellement leur texte lorsqu'ils sont pressés. Le dernier bouton doit vous permettre de quitter le programme ;
  • créez de très gros, et de très petits, boutons dans la même fenêtre.

précédentsommairesuivant
Lorsque j'ai essayé cet exemple sous Windows 95, je n'ai pas obtenu la palette de couleurs du fichier GIF. Le problème est peut-être dû à ma carte graphique ou au pilote de cette carte sous Windows 95, ce problème peut donc ne pas survenir sur votre machine.
Le bouton 1 de la souris est celui se trouvant le plus à gauche, le bouton 2 est celui du milieu et le bouton 3, celui de droite.
Connu sous le titre Programming Perl (traduit en français : Programmation en Perl) et édité par les éditions O'Reilly & Associates ; Inc.
Le système de numérotation des versions de Perl/Tk suit celui de Tcl/Tk. Je ne sais pas pourquoi ils ont sauté les versions 5, 6 et 7 (NDT Cette nouvelle numérotation de Tk a été faite pour suivre celle de Tcl).
Toutes les fontes n'existent pas sur tous les systèmes, bien que la fonte par défaut pour votre système devrait fonctionner. Utilisez l'instruction @config=$bouton->configure(-font);print"@config\n"; pour connaître cette fonte par défaut.
Bien que nous traitions ici de couleurs, les figures de ce livre sont en noir et blanc. L'utilisation de couleurs dans les figures rendrait malheureusement le livre trop cher à produire. J'ai essayé de choisir des couleurs suffisamment contrastées afin d'obtenir des figures aussi précises que possible. Le meilleur moyen de vérifier ce qui se passe avec chaque couleur est d'essayer, et d'exécuter les exemples.
Le curseur affiché dépend du gestionnaire de fenêtres utilisé, mais, la plupart du temps, c'est une flèche.
Sur les systèmes Win32, le rectangle de focus est représenté par une ligne en pointillés dans le widget.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

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.