Introduction à Perl/Tk

Interfaces graphiques avec Perl


précédentsommairesuivant

V. Les widgets étiquette et de saisie

Vous souhaitez parfois que l'utilisateur saisisse des informations précises, telles que son nom, adresse, ou même un numéro de série. Le moyen le plus simple de s'acquitter de cette tâche consiste à utiliser des widgets de saisie (entry widget). On peut utiliser un widget étiquette (label widget) avec un widget de saisie afin d'indiquer clairement à l'utilisateur ce qu'il doit y mettre. Vous verrez que les combinaisons de widgets étiquette et de saisie sont le plus souvent utilisées dans une fenêtre de type « saisie dans une base de données », où se trouvent de nombreux éléments d'information que l'utilisateur doit fournir.

V-A. Le widget Label

Jusqu'à maintenant, nous n'avons parlé que de boutons, de boutons et encore de boutons. Que faire si l'on veut uniquement placer un simple texte d'information à l'écran ? Le widget étiquette fait exactement cela : une étiquette est comme un bouton qui ne ferait rien. C'est un widget non interactif qui, par défaut, ne peut avoir le focus clavier (ce qui signifie que l'on ne peut le sélectionner en utilisant une tabulation) et qui ne fait rien lorsque l'on clique dessus.

Le widget étiquette est probablement le widget le plus simple. Il ressemble à un bouton en ce qu'il peut afficher du texte (ou un bitmap), être mis en relief (il est plat, par défaut), afficher plusieurs lignes de texte, avoir une fonte différente, etc. La figure 5.1 montre une simple fenêtre, possédant un bouton et une étiquette, et créée à l'aide du code suivant :

 
Sélectionnez
use Tk;

$mw = MainWindow->new();
$mw->Label( -text => "Étiquette" )->pack();
$mw->Button( -text => "Fin", -command => sub { exit } )->pack();

MainLoop;
Image non disponible
Figure 5.1 : Une simple fenêtre, avec une étiquette et un bouton

Voici quelques utilisations typiques d'une étiquette :

  • on place une étiquette à gauche d'un widget de saisie pour que l'utilisateur sache quel est le type de donnée attendu ;
  • on place une étiquette au-dessus d'un groupe de boutons radio, afin de préciser leur rôle (« Couleur de fond », par exemple). On peut faire la même chose avec des cases à cocher si celles-ci ont un rapport les unes avec les autres ou traitent du même thème ;
  • on utilise une étiquette pour indiquer aux utilisateurs l'erreur qu'ils ont faite : « Le nombre saisi doit être compris entre 10 et 100 » (on utilisera généralement un widget de dialogue pour afficher ce type de messages, mais ce n'est pas obligatoire) ;
  • on place une ligne d'information en bas d'une fenêtre. Tous les autres widgets devraient avoir un dispositif permettant d'afficher un texte décrivant leur rôle.

V-A-1. Création d'une étiquette

La méthode permettant de créer une étiquette est Label : en voici une utilisation classique :

 
Sélectionnez
$etiquette = $parent->Label( [ option => valeur . . . ] )->pack();

Bien sûr, maintenant que vous avez l'habitude des méthodes de création d'un widget, vous savez que, lorsque vous créez une étiquette, vous pouvez préciser certaines options permettant de modifier son apparence et son comportement.

V-A-2. Options des étiquettes

La liste suivante présente de manière exhaustive les options des étiquettes :

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

  • Permet de positionner le texte à la position spécifiée dans le widget. Plus le widget est grand, plus cet effet est notable.

-background => couleur

  • Configure la couleur de fond de l'étiquette.

-bitmap => bitmap

  • Affiche le bitmap bitmap à la place du texte.

-borderwidth => montant

  • Change la largeur des bords de l'étiquette.

-cursor => nom_curseur

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

-font => nom_fonte

  • Change la fonte du texte du widget.

-foreground => couleur

  • Change la couleur du texte (ou du bitmap) en couleur.

-height => montant

  • Configure la hauteur de l'étiquette : montant est exprimé en distances d'écran.

-highlightbackground => couleur

  • Configure la couleur du rectangle de focus autour du widget lorsque celui-ci n'a pas le focus.

-highlightcolor => couleur

  • Configure la couleur du rectangle de focus autour du widget lorsque celui-ci a le focus.

-highlightthickness => montant

  • Configure l'épaisseur du rectangle de focus. La valeur par défaut pour une étiquette est de 0.

-image => $ptr_img

  • Affiche l'image pointée par $ptr_img à la place du texte.

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

  • Indique le bord de l'étiquette contre lequel s'alignera un texte de plusieurs lignes.

-padx => montant

  • Ajoute des espaces à gauche et à droite du texte dans l'étiquette.

-pady => montant

  • Ajoute des espaces au-dessus et en dessous du texte dans l'étiquette.

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

  • Modifie le type du contour tracé autour de l'étiquette.

-takefocus => 0 | 1 | undef

  • Indique si le widget peut prendre le focus ou non.

-text => texte

  • Indique le texte affiché par l'étiquette.

-textvariable => \$variable

  • Pointeur vers une variable contenant le texte à afficher par l'étiquette. L'étiquette se modifiera automatiquement en même temps que $variable.

-underline => n

  • Souligne le nième caractère du texte. Permet à cette touche d'invoquer le widget lorsqu'il a le focus. La valeur par défaut est - (pas de caractère souligné).

-width => montant

  • Configure la largeur de l'étiquette à montant.

-wraplength => montant

  • Indique que le texte de l'étiquette passera à la ligne lorsqu'il dépassera ce montant.

Cette liste décrit brièvement chaque option. Certaines d'entre elles ont des valeurs par défaut différentes de celles déjà vues avec les différents widgets boutons, une étiquette se comporte donc un peu différemment de ceux-ci.

V-A-3. Différences entre les étiquettes et les autres widgets

Lorsque nous avons créé des widgets boutons, nous pouvions cliquer dessus avec la souris, ou les sélectionner avec la touche de tabulation et les presser en utilisant le clavier. Un widget étiquette, par contre, n'interagit pas avec l'utilisateur : il est là dans le seul but d'informer et n'a donc pas d'option -command. On ne peut pas tabuler vers un widget étiquette, car rien ne se passerait.

La valeur par défaut de -takefocus, 0, rend l'étiquette non interactive. Lorsque l'on passe en tabulant sur les widgets de l'écran, le rectangle de focus nous indique quel est le widget qui a le focus clavier à un instant donné. Comme nous ne permettons pas à une étiquette d'avoir ce focus (rappelez-vous la valeur de 0 pour -takefocus), cela n'aurait pas de sens qu'elle ait un rectangle de focus visible. La valeur par défaut de l'option -highlightthickness d'une étiquette est 0. On peut matérialiser un rectangle autour d'une étiquette en mettant une valeur supérieure pour -highlightthickness et en configurant -highlightbackground avec une couleur comme bleu ou rouge.

Le widget étiquette n'a pas non plus d'option -state :comme on ne peut pas cliquer sur une étiquette, il n'y a aucune raison de la désactiver.

V-A-4. Styles d'étiquettes

La figure 5.2 montre les effets de la modification de l'option -relief d'une étiquette. Notez que le contour du widget est très près du texte. À la différence d'un bouton, on ne souhaite généralement pas d'espace supplémentaire autour de l'étiquette (cet espace est contrôlé par les options -padx et -pady). Normalement, on souhaite qu'une étiquette se trouve le plus près possible du, ou des, widget(s) qu'elle décrit.

Vous remarquerez que j'aime voir ce que donnent les widgets lorsqu'ils ont des contours différents.

Cela aide parfois à déterminer l'endroit où un widget se termine, notamment dans le cas des widgets ayant une valeur par défaut égale à 'flat'. De plus, je change souvent le contour des différents widgets pour m'assurer de l'emplacement de chacun d'eux à l'écran. Lorsque l'on a créé 10 entrées et étiquettes ayant des noms abscons, il est facile de perdre le fil. De même, changer la largeur du bord d'un widget le fait ressortir. Bien sûr, je reconfigure toujours le contour et sa largeur avec des valeurs plus supportables avant de laisser quelqu'un d'autre exécuter le programme ! La couleur est aussi un bon moyen de diagnostiquer les interfaces créées.

Image non disponible
Figure 5.2 : Étiquettes avec des contours différents. La fenêtre du bas a -borderwidth => 10

V-A-5. Exemple de message d'état

J'utilise souvent les reliefs 'groove' ou 'ridge' lorsque je crée une étiquette d'aide ou d'état en bas d'une fenêtre. Je place cette étiquette à l'aide du gestionnaire d'espace pack en utilisant les options -side => 'bottom' et -fill => 'x'. Il y a deux façons d'utiliser une étiquette d'état :

  • on configure la variable qui lui est associée pour qu'elle change au fur et à mesure que le programme progresse, et qu'elle prévienne l'utilisateur que le travail est en cours, ou que quelque chose se passe ;
  • on fait en sorte qu'une étiquette d'aide donne des informations sur chacun des widgets de l'application lorsqu'ils ont le focus. Pour cela, on utilise la méthode bind.

Ces deux types d'utilisation sont montrés dans l'exemple de code suivant :

Ce code affiche une étiquette d'aide de type « Action en cours » :

 
Sélectionnez
$mw->Label(
    -textvariable => \$message,
    -borderwidth  => 2,
    -relief       => 'groove'
)->pack(
    -fill => 'x',
    -side => 'bottom'
);
$mw->Text()->pack(
    -side   => 'top',
    -expand => 1,
    -fill   => 'both'
);
$message = "Chargement du fichier index.html..."; 
... 
$message = "Terminé";

L'étiquette est créée en bas de l'écran. On la place d'abord, car on veut qu'elle reste à l'écran si l'on modifie la taille de la fenêtre (rappelez-vous que les derniers widgets placés avec pack auront une priorité inférieure si la fenêtre manque de place). Au fur et à mesure que le programme s'exécute (ce que l'on représente par la ligne …), il modifie l'étiquette en conséquence.

Ce code donne un exemple d'utilisation d'une étiquette d'aide pour l'utilisation des widgets :

 
Sélectionnez
$mw->title("Exemple d'étiquette d'aide");

$mw->Label(
    -textvariable => \$message,
    -relief       => 'groove'
)->pack(
    -side => 'bottom',
    -fill => 'x'
);

$b1 = $mw->Button(
    -text    => "Fin",
    -command => \&exit
)->pack( -side => 'left' );
&lier_message( $b1, "Cliquez pour quitter l'application" );

$b2 = $mw->Button( -text => "Ne rien faire" )->pack( -side => 'left' );
&lier_message( $b2, "Ce bouton ne fait absolument rien !" );

$b3 = $mw->Button(
    -text    => "Quelque chose",
    -command => sub { print "Quelque chose\n"; }
)->pack( -side => 'left' );
&lier_message( $b3, "Affiche le texte 'Quelque chose'" );

sub lier_message {
    my ( $widget, $msg ) = @_;
    $widget->bind( '<Enter>', [ sub { $message = $_[1]; }, $msg ] );
    $widget->bind( '<Leave>', sub { $message = ""; } );
}

Cet exemple est un peu plus long, car nous avons utilisé la méthode bind (expliquée en détail au chapitre 14, Liaisons d'événements). On veut associer un message d'aide à chaque widget créé : pour ce faire, on ajoute des liaisons à chaque widget afin de changer le contenu de la variable $message en une chaîne donnée lorsque la souris passe sur le widget, et en une chaîne vide lorsque la souris s'en éloigne. On utilise une fonction afin d'éviter de répéter à chaque fois les mêmes lignes de liaison. La figure 5.3 montre à quoi ressemble notre fenêtre lorsque la souris est au-dessus du bouton du milieu.

La figure 5.3 montre que le texte d'exemple est centré dans le widget étiquette. Lorsque l'on utilise des étiquettes de plusieurs lignes, et que l'on élargit le widget sur toute la largeur de l'écran, le texte reste centré, même si l'on utilise l'option -justify => 'left'. On peut contourner ce problème en créant un cadre (frame) conteneur, en lui donnant le contour voulu, en élargissant le cadre (au lieu de l'étiquette) à la largeur de l'écran et en plaçant le widget étiquette dans ce cadre :

 
Sélectionnez
$cadre = $mw->Frame(
    -relief      => 'groove',
    -borderwidth => 2
)->pack(
    -side => 'bottom',
    -fill => 'x'
);
$cadre->Label( -textvariable => \$message, )->pack( -side => 'left' );
Image non disponible
Figure 5.3 : Fenêtre avec étiquette d'aide

Cela permet à l'étiquette de s'agrandir et de se réduire autant que nécessaire dans le cadre, tout en collant le texte sur le bord gauche. Si vous tapez ce court exemple, et que vous jouez avec les chaînes liées à chaque widget, vous remarquerez que la fenêtre changera elle-même de taille si le texte assigné à $message est trop long pour s'afficher sur l'étiquette. Cela peut être ennuyeux si la fenêtre est d'abord assez petite. Il y a deux manières de gérer cela : vous pouvez faire en sorte de toujours utiliser des messages courts, ou demander à la fenêtre de ne pas changer de taille lorsque celle de l'étiquette est modifiée.

Les inconvénients de chaque approche ne sont pas trop terribles et celle que vous choisirez dépendra simplement de l'application sur laquelle vous travaillez. Si vous pouvez faire des phrases vraiment courtes et ayant un sens, c'est parfait. Demander à la fenêtre de ne pas modifier sa taille est presque aussi simple, il suffit d'ajouter une seule ligne à votre programme :

 
Sélectionnez
$mw->packPropagate(0);

L'utilisation de packPropagate fait que votre fenêtre ne changera pas de taille lorsqu'un widget y est placé (nous avons déjà parlé de packPropagate au chapitre 2, Gestion de l'espace). Cela signifie que votre fenêtre peut ne pas montrer tous les widgets tout de suite. Vous pouvez gérer cela en continuant avec la fenêtre telle quelle est jusqu'à ce que tous vos widgets soient placés, puis en trouvant une taille de départ convenable pour votre fenêtre et en utilisant $mw->geometry(taille) pour demander cette taille initiale (voir le chapitre 13, Widgets de premier niveau, pour les informations concernant la méthode geometry).

V-A-6. Configuration d'une étiquette

Une étiquette est un widget assez ennuyeux et il n'y a donc que deux méthodes permettant de modifier ou d'obtenir des informations sur elle : cget et configure. Ces deux méthodes fonctionnent pour le widget Label de la même façon que pour le widget Button. Reportez-vous à l'annexe A pour les détails sur les paramètres et les valeurs de retour de ces méthodes.

V-B. Le widget Entry

Jusqu'à maintenant, le seul moyen dont on disposait pour permettre à l'utilisateur d'intervenir était un clic de souris sur un bouton (widgets Button, Checkbutton, ou Radiobutton), géré via l'option -command. Bien qu'il soit utile de pouvoir cliquer avec la souris, c'est aussi limité. Le widget de saisie (entry widget) permet à l'utilisateur de taper du texte pouvant ensuite être utilisé d'une façon ou d'une autre par l'application. Voici quelques exemples de situations où l'on peut utiliser un widget de saisie :

  • dans un formulaire de base de données nécessitant une saisie par champ (prénom, nom, adresse, par exemple) ;
  • dans une fenêtre d'enregistrement de la licence d'un logiciel, nécessitant un numéro de série ;
  • dans une fenêtre d'ouverture de session, nécessitant un nom d'utilisateur et un mot de passe ;
  • dans une fenêtre de configuration, afin de donner le nom d'une imprimante ;
  • dans une fenêtre d'ouverture de fichier, nécessitant de préciser le chemin et le nom d'un fichier.

Normalement, on ne se soucie pas de ce que tapent les utilisateurs dans un widget de saisie tant qu'ils n'ont pas fini cette saisie et tout traitement se fera « après coup », lorsque l'utilisateur cliquera sur un bouton de type « Appliquer ». On peut s'amuser à traiter chaque caractère au fur et à mesure qu'il est tapé en configurant une liaison compliquée, mais cela n'en vaut probablement pas la peine.

L'utilisateur peut taper n'importe quoi dans un widget de saisie ; c'est au programmeur de décider si le texte entré est correct ou non. Avant d'utiliser l'information saisie, on doit réaliser quelques tests afin de détecter d'éventuelles erreurs : si l'on attend un entier et que l'on obtient des caractères alphabétiques, on doit produire un message d'avertissement ou d'erreur afin de prévenir l'utilisateur.

Un widget de saisie est bien plus complexe qu'il n'y parait au premier abord : c'est, en fait, un éditeur de texte simplifié et réduit à une seule ligne. On peut y taper du texte, le sélectionner à la souris, l'effacer ou en ajouter. Je classerais un tel widget comme un widget de « milieu de gamme », car il est plus compliqué qu'un bouton, mais bien moins que les widgets texte ou canevas.

V-B-1. Création d'un widget de saisie

Sans surprise :

 
Sélectionnez
$saisie = $parent->Entry( [ option => valeur . . . ] )->pack;

Lorsque le widget de saisie est créé, il est initialement vide de tout texte, et le point d'insertion (si le widget a le focus clavier) se trouve à son extrême gauche.

V-B-2. Options d'un widget de saisie

La liste suivante contient une brève description de chacune des options de configuration d'un widget de saisie. Plusieurs d'entre elles sont traitées de façon plus détaillée dans la suite de ce chapitre.

-background => couleur

  • Configure la couleur de fond du widget de saisie (zone derrière le texte).

-borderwidth => montant

  • Configure l'épaisseur du contour du widget. La valeur par défaut est 2.

-cursor => nom_curseur

  • Indique que le curseur se transformera en nom_curseur lorsqu'il sera au-dessus du widget.

-exportselection => 0 | 1

  • Si la valeur booléenne est vraie, tout texte sélectionné sera exporté vers le bloc-notes (clipboard) du système de fenêtrage.

-font => nom_fonte

  • Change la fonte affichée dans la zone de saisie.

-foreground => couleur

  • Change la couleur du texte.

-highlightbackground => couleur

  • Configure la couleur qu'aura le rectangle de focus lorsque le widget n'a pas le focus clavier.

-highlightcolor => couleur

  • Configure la couleur qu'aura le rectangle de focus lorsque le widget détiendra le focus clavier.

-highlightthickness => montant

  • Configure la largeur du rectangle de focus autour du widget. La valeur par défaut est 2.

-insertbackground => couleur

  • Configure la couleur du point d'insertion.

-insertborderwidth => montant

  • Configure la largeur du contour du point d'insertion. Cette option est normalement utilisée avec les options -ipadx et -ipady du gestionnaire d'espace.

-insertofftime => millisecondes

  • Configure la durée pendant laquelle le point d'insertion disparaît du widget de saisie (cadence de clignotement).

-insertontime => millisecondes

  • Configure la durée pendant laquelle le point d'insertion apparaît dans le widget de saisie (cadence de clignotement).

-insertwidth => montant

  • Configure la largeur du point d'insertion. La valeur par défaut est 2.

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

  • Configure l'alignement du texte dans le widget de saisie (à gauche, par défaut).

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

  • Modifie l'aspect du contour du widget de saisie.

-selectbackground => couleur

  • Configure la couleur de fond du texte sélectionné dans le widget de saisie.

-selectborderwidth => montant

  • Indique la largeur du contour de la mise en évidence de la sélection.

-selectforeground => couleur

  • Configure la couleur du texte sélectionné dans le widget de saisie.

-show => caractère

  • Indique quel est le caractère qui sera affiché à la place du texte réellement tapé.

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

  • Configure l'état du widget. La valeur par défaut est 'normal'.

-takefocus => 0 | 1 | undef

  • Précise si le widget pourra prendre le focus clavier ou non.

-textvariable => \$variable

  • Précise la variable associée à l'information tapée dans le widget de saisie.

-width => montant

  • Indique la largeur de la saisie en nombre de caractères.

-xscrollcommand => fct_rappel

  • Assigne une fonction de rappel à utiliser lorsque l'on circule dans le widget.

Les options suivantes se comportent comme on peut s'y attendre, et ne méritent pas plus de précisions : -background, -cursor, -font, -highlightbackground, -highlightcolor, -highlightthickness, -foreground, -justify, -takefocus, et -state. Pour des explications supplémentaires quant à leurs effets sur un widget, voir le chapitre 3 33.

V-B-3. Assignation du contenu de la saisie à une variable

L'option -textvariable permet de savoir ce que l'utilisateur a entré dans le widget de saisie :

 
Sélectionnez
-textvariable => \$variable

Cette option devrait déjà vous être familière grâce aux différents exemples donnés avec le widget bouton. Toute entrée de texte dans le widget de saisie sera assignée à cette variable. L'inverse est aussi vrai : toute chaîne assignée à la variable s'affichera dans le widget de saisie.

Il est important de se rappeler que tout ce que saisit l'utilisateur sera affecté à cette variable. Cela signifie que, même si l'on attend une entrée numérique (314, par exemple), on peut obtenir quelque chose comme 3s14 si l'utilisateur a pressé accidentellement (ou à dessein) la ou les mauvaises touches. Avant d'utiliser les informations obtenues à partir d'un widget de saisie, il est préférable de vérifier celles-ci afin de s'assurer qu'elles soient ce que l'on attendait ou, vraiment au pire, qu'elles soient dans un format correct. Essayer d'utiliser « 3s14 » dans une équation donnerait, à coup sûr, des résultats inattendus.

L'autre moyen de récupérer ce qui se trouve dans le widget de saisie consiste à utiliser la méthode get :

 
Sélectionnez
$valeur = $saisie->get();

On peut utiliser get, que l'option -textvariable soit positionnée ou non.

V-B-4. Styles d'une zone de saisie

Comme pour tous les widgets, on peut modifier le tracé des contours en utilisant les options -relief et/ou -borderwidth :

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

Pour un widget de saisie, la valeur par défaut est 'sunken', ce qui est différent de ce que nous avons vu jusqu'à maintenant. La figure 5.4 montre les différents types de contours avec différentes valeurs de -borderwidth : celle par défaut (2), 4 et 10.

Voici le code ayant servi à créer les cinq zones de saisie. On utilise le nom du type de contour comme texte du widget.

 
Sélectionnez
$largeur = 2;    # puis 4, puis 10
foreach (qw/flat groove raised ridge sunken solid/) {
    $saisie = $mw->Entry(
        -relief      => $_,
        -borderwidth => $largeur
    )->pack( -expand => 1 );
    $saisie->insert( 'end', $_ );    # place du texte dans la zone de saisie
}
Image non disponible
Figure 5.4 : Les différents contours d'un widget de saisie : -borderwidth de 2 (défaut), 4 et 10

V-B-5. Indices de saisie

Afin de manipuler le texte dans une zone de saisie, il faut un moyen d'identifier des parties ou des positions précises de ce texte. En fait, l'exemple ci-dessus utilisait un indice : la ligne $saisie->insert('end', $_) utilise l'indice 'end'. Comme la méthode insert (étudiée plus loin dans ce chapitre), toutes les méthodes nécessitant des informations sur une position donnée ont besoin d'un indice (ou de deux, si l'information concerne un ensemble de caractères). Celui-ci peut être aussi simple que 0, qui indique le tout début du texte, ou quelque chose de plus compliqué, comme 'insert'.

Voici les différentes formes d'indices et leur signification :

n (un entier quelconque)

  • Position ordinale d'un caractère. 0 est la position du premier caractère de la chaîne. Si la zone de saisie contient « Ta mère, son mot de passe c'est 'toto' ! » et que l'on utilise un indice de 13, le caractère ainsi désigné sera le « m » du mot « mot ».

'insert'

  • Désigne le caractère placé immédiatement après le point d'insertion, cette petite barre rigolote qui s'affiche dans la zone de saisie lorsque l'on y tape du texte. On peut déplacer ce point à l'aide des touches fléchées ou en cliquant sur un autre emplacement du widget.

'sel.first'

  • Le premier caractère de la chaîne sélectionnée. Une erreur se produira s'il n'existe pas de sélection. La chaîne sélectionnée est celle qui est créée à l'aide de la souris ou de la combinaison 'Maj-flèche' : elle apparaît légèrement surélevée par rapport au fond du widget.
  • Si le texte sélectionné dans cette chaîne est le mot « passe » (montré ici en gras)

     
    Sélectionnez
    Ta mère, son mot de passe c'est 'toto' !
  • 'sel.first' désignera le caractère « p ».

'sel.last'

  • Le caractère situé immédiatement après le dernier caractère de la chaîne sélectionnée. Une erreur se produira s'il n'existe pas de sélection dans la zone de saisie. Avec l'exemple précédent, cela désignerait l'espace après le « e » de « passe ».

'anchor'

  • Cet indice évolue selon ce qui se passe avec le texte sélectionné dans la zone de saisie. Par défaut, il débute à l'extrême gauche du widget (0). Il est modifié si l'on clique à n'importe quel endroit de la zone de saisie : sa nouvelle valeur sera alors la position sur laquelle on a cliqué. L'indice 'anchor' sera également modifié lorsque l'on fait une nouvelle sélection -- avec la souris ('anchor' sera à l'endroit où vous avez cliqué) ou en faisant la combinaison `Maj'-clic gauche ('anchor' sera positionné au début de la sélection). La plupart du temps, cet indice est utilisé de façon interne et l'on trouve rarement des cas où il serait utile à une application.

'end'

  • Désigne le caractère placé immédiatement après le dernier de la chaîne. Sa valeur est la même que si l'on avait spécifié la longueur totale de la chaîne avec un indice numérique.

@x

  • Cette forme utilise une coordonnée x, présente dans la zone de saisie. Le caractère situé à cette coordonnée sera utilisé. @0 désigne le caractère le plus à gauche (le premier) du widget de saisie. Vous utiliserez rarement cette forme d'indice.

V-B-6. Options de sélection du texte

Lorsque l'on sélectionne du texte dans un widget de saisie, plusieurs choses se passent. Les indices 'sel.first' et 'sel.last' pointent, respectivement, sur le début et la fin du texte sélectionné. Sous Unix, on peut aussi copier la sélection dans le bloc-notes à l'aide de l'option -exportselection :

  • -exportselection => 0 | 1

Cette option indique si le texte sélectionné dans la zone de saisie doit, ou non, être aussi placé dans le tampon de sélection en plus d'être stocké de façon interne par le widget. La valeur par défaut fait que le texte sélectionné peut être copié-collé dans d'autres applications.

Les options -selectbackground, -selectforeground et -selectborderwidth permettent d'intervenir sur les couleurs utilisées par la sélection :

 
Sélectionnez
-selectbackground => couleur 
-selectforeground => couleur
-selectborderwidth => montant

-selectbackground et -selectforeground modifient les couleurs du texte et de la zone derrière lui lorsque ce texte est mis en évidence. Le mot « texte » de la figure 5.5 est sélectionné.

Image non disponible
Figure 5.5 : Zone de saisie avec -selectbackground => `red' et -selectforeground => `yellow'

On peut changer la largeur du contour de la boîte de sélection à l'aide de -selectborderwidth. Si l'on conserve la taille du widget de saisie, les effets ne seront pas visibles, car le widget coupe la boîte de sélection. Pour réellement voir les résultats de l'augmentation de la valeur de -selectborderwidth, il faut utiliser cette option au moment de la création du widget, ainsi que les options -ipadx et -ipady du gestionnaire d'espace utilisé.

Image non disponible
Figure 5.6 : Zone de saisie avec -selectborderwidth => 10

On modifie généralement la valeur de -selectborderwidth afin d'ajouter un peu d'espace supplémentaire autour du texte ou pour vraiment mettre en évidence ce qui est sélectionné. Voici le code qui a permis de créer le widget de saisie de la figure 5.6 :

 
Sélectionnez
$saisie = $mw->Entry( -selectborderwidth => 10 )->pack(
    -expand => 1,
    -fill   => 'x',
    -ipadx  => 10,
    -ipady  => 10
);
$saisie->insert( 'end', 'Sélectionnez le mot texte de cette phrase' );

Remarquez bien les options -ipadx et -ipady de la méthode pack.

V-B-7. Le point d'insertion

Le point d'insertion est cette petite barre clignotante, placée dans le widget de saisie lorsqu'il a le focus clavier. Si un autre widget a le focus, le point d'insertion reste là, mais est invisible (il en va de même lorsqu'aucun widget n'a le focus). Dans la figure 5.7, le point est situé tout de suite après le premier « n » du mot « insertion ».

Image non disponible
Figure 5.7 : Point d'insertion par défaut

On peut modifier l'épaisseur, la largeur du bord et la couleur du point d'insertion à l'aide des options suivantes :

 
Sélectionnez
-insertbackground => couleur 
-insertborderwidth => montant 
-insertwidth => montant

L'option -insertwidth modifie simplement la largeur du point d'insertion afin qu'il apparaisse plus gros ; -insertbackground en change la couleur générale. La figure 5.8 montre un exemple de modification du point d'insertion à l'aide de ces deux options :

Image non disponible
Figure 5.8 : Point d'insertion avec -insertbackground => 'green' et -insertwidth => 10

Le point d'insertion, quelle que soit la largeur, est toujours centré entre deux caractères. Le point d'insertion de la figure 5.8 se trouve au même endroit que dans la figure 5.7. Cela peut distraire les utilisateurs et rendre les choses confuses inutilement ; il est donc préférable de ne pas modifier l'option -insertwidth.

On peut donner un aspect tridimensionnel au point d'insertion en utilisant l'option -insertborderwidth (comme dans la figure 5.9). Cette option, tout comme -insertwidth n'a pas beaucoup d'intérêt pratique.

On peut aussi modifier la cadence de clignotement du point à l'aide des options suivantes :

Image non disponible
Figure 5.9 : Point d'insertion avec -insertborderwidth => 5, -insertbackground => 'green' et -insertwidth => 10
 
Sélectionnez
-insertofftime => millisecondes 
-insertontime => millisecondes

La valeur par défaut de -insertofftime est de 300 millisecondes, celle de -insertontime est de 600 millisecondes. Ces durées font que le point reste visible deux fois plus longtemps qu'il n'est caché. Les valeurs de ces options doivent être positives ou nulles.

Pour disposer d'un point d'insertion vraiment frétillant, il suffit d'utiliser des valeurs beaucoup plus petites pour ces deux options. Pour un point calme et tranquille, on double les durées. Si l'on ne veut pas que le point clignote, il suffit de mettre -insertofftime à 0.

V-B-8. Saisies de mots de passe

Dans certains cas, l'information saisie par l'utilisateur ne doit pas s'afficher à l'écran. Pour afficher autre chose que le texte réellement tapé, on utilise l'option -show :

 
Sélectionnez
-show => caractère

La valeur de cette option est un caractère simple, qui sera affiché à la place des caractères tapés. Pour une saisie de mot de passe, par exemple, on peut utiliser des astérisques (voir la figure 5.10). Si l'on donne une chaîne comme valeur, seul le premier caractère de celle-ci sera utilisé. Par défaut, cette option n'est pas définie et tout ce que tape l'utilisateur s'affichera tel quel.

Image non disponible
Figure 5.10 : Zone de saisie affichant un mot de passe

Lorsque l'on utilise l'option -show, l'information stockée dans la variable référencée par -textvariable sera l'information réelle, pas les astérisques.

Si cette option est utilisée, l'utilisateur ne peut couper et coller le mot de passe (quelle que soit la valeur de -exportselection). S'il est coupé et collé vers un autre écran, ce que l'utilisateur voyait (les astérisques, par exemple) est vraiment collé, mais pas l'information qui se cache derrière. On pourrait se dire qu'en configurant ensuite le widget de saisie en faisant $saisie->configure(-show => ""), les mots entrés par l'utilisateur réapparaîtraient soudainement. Heureusement qu'il n'en est rien : un ensemble de \x0 (du charabia, quoi) s'affichera à la place. Toute variable associée à la saisie via l'option -textvariable contiendra quand même l'information correcte. Si vous faites $saisie->get(), cette information correcte (non déformée) sera renvoyée. La méthode get est décrite plus bas dans ce chapitre.

V-B-9. Utilisation d'une barre de défilement

Si l'information demandée à l'utilisateur est susceptible de devenir plutôt longue, celui- ci peut alors utiliser les touches fléchées pour faire défiler le texte. Pour faciliter ce déplacement, on peut créer une barre de défilement horizontale et l'affecter au widget de saisie via l'option -xscrollcommand :

 
Sélectionnez
-xscrollcommand => [ 'set' => $barre_defil ]

Pour le moment, je ne présenterai que le moyen le plus simple d'affecter une barre de défilement à un widget de saisie. Le chapitre 6, Barres de défilement, donnera plus de détails.

Pour créer une barre de défilement et l'associer à un widget de saisie, on écrit :

 
Sélectionnez
# crée la barre de défilement
$defil = $mw->Scrollbar( -orient => "horizontal" );

# crée la zone de saisie
$saisie = $mw->Entry( -xscrollcommand => [ 'set' => $defil ] )->pack( -expand => 1, -fill => 'x' );
$defil->pack( -expand => 1, -fill => 'x' );

# on les lie
$defil->configure( -command => [ $saisie => 'xview' ] );
$saisie->insert( 'end', "Chaîne vraiment très très très très très très très très longue" );

La figure 5.11 montre le résultat : à gauche, la fenêtre après sa création et, à droite, après s'être déplacé complètement à droite à l'aide de la barre de défilement.

Image non disponible
Figure 5.11 : Barre de défilement avec un widget de saisie

Les cas où vous devrez utiliser une barre de défilement avec un widget de saisie sont très rares. Une barre double l'espace utilisé et l'on peut obtenir les mêmes avantages en utilisant simplement les touches fléchées lorsque le widget a le focus. Si l'utilisateur doit saisir plusieurs lignes de texte, il est préférable d'utiliser plutôt un widget texte. Le chapitre 8, Le widget texte, donne plus d'informations sur ce qu'un tel widget peut faire.

V-B-10. Configuration d'un widget de saisie

Les méthodes configure et cget fonctionnent avec le widget de saisie de la même façon qu'avec tous les autres. Leurs options par défaut pour ce widget sont énumérées à l'annexe A, Configuration des widgets avec configure et cget.

V-B-11. Suppression de texte

On peut utiliser la méthode delete pour supprimer une partie, ou la totalité, du texte contenu dans la zone de saisie. Pour ôter plus de deux caractères, on utilisera un intervalle d'indices, et un indice simple pour n'en ôter qu'un.

 
Sélectionnez
$saisie->delete( indice_debut [ , indice_fin] )

Pour supprimer tout le texte, on peut écrire $saisie->delete(0, 'end'). Si l'on utilise l'option -textvariable, on peut aussi détruire ce texte en réaffectant une chaîne vide à la variable : $variable = "".

Voici d'autres exemples d'utilisation de la méthode delete :

 
Sélectionnez
$saisie->delete(0); # ne supprime que le premier caractère 
$saisie->delete(1); # supprime le second caractère 
$saisie->delete('sel.first', 'sel.last') # supprime le texte sélectionné 
if ($saisie->selectionPresent());        # s'il y a une sélection...

V-B-12. Déterminer le contenu d'un widget de saisie

Il y a deux moyens de déterminer le contenu d'un widget de saisie : utiliser la méthode get ou se servir de la variable associée à -textvariable.$texte_saisi = $saisie->get(), par exemple, mettra dans $texte_saisi le contenu complet du widget.

La façon de récupérer ce contenu dépend de ce vous comptez en faire. Si vous voulez simplement l'utiliser pour l'écrire dans un fichier ou l'insérer dans une base de données, il ne serait pas raisonnable de gaspiller de la mémoire en le stockant dans une variable : dans ce cas, il suffit d'utiliser la méthode get dans l'instruction print (ou dans toute instruction concernée). Si l'information saisie est une valeur qui sera souvent utilisée (un nombre pour un calcul mathématique, par exemple), il est alors conseillé de la stocker dès le départ dans une variable afin de pouvoir y accéder plus tard.

V-B-13. Déplacement du point d'insertion

La méthode icursor placera le point à l'indice spécifié :

 
Sélectionnez
$saisie->icursor(indice);

Par défaut, le point est à l'emplacement de la dernière insertion. Pour forcer celui-ci à aller ailleurs, on peut écrire quelque chose comme :

 
Sélectionnez
$s_texte = "Texte saisi"; 
$saisie = $mw->Entry(-textvariable => \$s_texte)->pack(); 
$saisie->focus; 
$saisie->icursor(1); # Place le point à cet indice

On utilise la méthode focus (qui n'est pas spécifique aux widgets de saisie, mais à tous les widgets) pour que l'application donne le focus à notre widget de saisie dès qu'elle démarre. Puis, nous plaçons le point d'insertion entre le premier et le deuxième caractère (d'indices 0 et 1). Voir le chapitre 16, Méthodes communes à tous les widgets, pour plus d'informations sur la notion de focus.

Si l'on commence le texte par une chaîne précise, on peut faire en sorte de déplacer la position de début de la saisie à un emplacement donné. On peut, par exemple, initialiser $s_texte avec la chaîne « http:// », puis utiliser l'instruction $saisie->icursor('end').

V-B-14. Obtenir la valeur d'un indice

La méthode index convertit un indice nommé en indice numérique :

 
Sélectionnez
$numindex = $saisie->index(indice);

L'une des applications de index est de rechercher le nombre de caractères dans la zone de saisie : $longueur = $saisie->index('end'). On aurait pu, évidemment, obtenir le même résultat en faisant $longueur = length($variable), si $variable est la variable utilisée avec l'option -textvariable.

On utilisera le code suivant afin de rechercher le début du texte sélectionné :

 
Sélectionnez
$indice_debut = $saisie->selectionPresent() ? 
                           $saisie->index('sel.first') : -1;

Nous traiterons de selectionPresent plus loin dans ce chapitre.

V-B-15. Insertion de texte

La méthode insert permet d'insérer une chaîne quelconque à partir de l'indice spécifié :

 
Sélectionnez
$saisie->insert(indice, chaîne);

Voici une application simple, utilisant insert :

 
Sélectionnez
#!/usr/bin/perl
use Tk;

$mw = MainWindow->new;
$mw->title("Saisie");

$s_texte = "Texte saisi";     # Crée une saisie avec un texte initial
$saisie = $mw->Entry( -textvariable => \$s_texte )->pack(
    -expand => 1,
    -fill   => 'x'
);
$mw->Button(
    -text    => "Fin",
    -command => sub { exit }
)->pack( -side => 'bottom' );

# Crée un bouton qui insérera un compteur à la position du point
$i = 1;
$mw->Button(
    -text    => "Insertion # ",
    -command => sub {
        if ( $saisie->selectionPresent() ) {
            $saisie->insert( 'sel.last', "$i" );
            $i++;
        }
    }
)->pack;

MainLoop;

On initialise la zone de saisie avec un texte par défaut : « Texte saisi ». Puis, on crée deux boutons : le premier est le célèbre bouton « Fin » qui nous permet de quitter l'application, le second est un peu plus compliqué. Lorsqu'il est pressé, il vérifie si du texte est sélectionné dans le widget $saisie : si c'est le cas, il insérera un nombre représentant le nombre de fois où l'on a cliqué sur le bouton « Insertion # ».

Image non disponible
Figure 5.12 : Utilisation de la méthode insert

Dans la figure 5.12, nous avons d'abord sélectionné le mot « Texte », puis nous avons cliqué quatre fois sur le bouton « Insertion # ». À chaque fois qu'il est pressé, celui-ci insère un nombre à l'indice 'sel.last'. Cet indice ne change pas entre deux clics sur le bouton, on a donc l'impression de compter à l'envers !

V-B-16. Parcours du texte

Deux méthodes, scanMark et scanDragto, permettent un parcours rapide d'une zone de saisie. Un appel à scanMark mémorise simplement la coordonnée x qui lui est passée afin de l'utiliser plus tard avec scanDragto. Elle retourne une chaîne vide.

 
Sélectionnez
$saisie->scanMark(x1); 
$saisie->scanDragto(x2);

scanDragto est la compagne de scanMark : elle attend aussi une coordonnée x et la compare à celle passée à scanMark. La partie visible de la zone de saisie est ajustée de dix fois la différence entre les deux coordonnées.

V-B-17. Utilisation du texte sélectionné

La méthode selection accepte plusieurs listes de paramètres différentes. Si l'on consulte la documentation en ligne, il y est écrit que l'on peut utiliser :

 
Sélectionnez
$saisie->selectionAdjust(indice);

Vous verrez aussi la forme $saisie->selection('adjust', indice ), où 'adjust' est le premier paramètre. Sachez que ces deux formes signifient exactement la même chose et que vous pouvez rencontrer l'une ou l'autre.

On peut positionner la sélection à un indice donné en utilisant la méthode selectionAdjust :

 
Sélectionnez
$saisie->selectionAdjust(indice);

Cette instruction aura pour effet d'étendre le texte sélectionné en direction de l'indice (vers quelque extrémité la plus proche qui soit).

Pour annuler la sélection :

 
Sélectionnez
$saisie->selectionClear();

Cela supprimera du widget de saisie tout indicateur de sélection, et les indices 'sel.first' et 'sel.last' seront alors indéfinis. Le texte sélectionné n'est pas supprimé.

Pour affecter un indice donné à l'indice 'anchor', on utilise la méthode selectionFrom :

 
Sélectionnez
$saisie->selectionFrom(indice);

Cette instruction n'affecte pas le texte sélectionné ni les indices 'sel.first' et 'sel.last'.

Le seul moyen de vérifier si une sélection a été faite dans le widget de saisie consiste à utiliser la méthode selectionPresent :

 
Sélectionnez
if ($saisie->selectionPresent()) { 
    # traitement de la sélection 
}

Cette méthode renvoie 1 si du texte est sélectionné, on peut donc utiliser sans problème les indices 'sel.first' et 'sel.last' (s'il n'y a pas de sélection, une erreur se produira lorsque l'on voudra utiliser l'un de ces indices). selectionPresent renvoie 0 si rien n'est sélectionné.

On peut modifier l'intervalle de sélection à l'aide de la méthode selectionRange :

 
Sélectionnez
$saisie->selectionRange(indice_début, indice_fin);

Les deux indices précisent l'étendue souhaitée de la sélection. Si indice_début est supérieur ou égal à indice_fin, la sélection est annulée, ce qui place 'sel.first' et 'sel.last' dans un état indéfini. Sinon, 'sel.first' et 'sel.last' vaudront respectivement la même chose que indice_début et indice_fin.

La méthode selectionTo forcera la nouvelle sélection à commencer au point 'anchor' courant pour se terminer à l'indice spécifié :

 
Sélectionnez
$saisie->selectionTo(indice);

V-B-18. Changer la vue d'un widget de saisie

Le rôle de la méthode xview dépend des paramètres qui lui sont passés.

Sans paramètre, elle renvoie une liste de deux éléments contenant des nombres de 0 à 1. Ceux-ci définissent ce qui est actuellement visible dans le widget de saisie. Le premier nombre indique le pourcentage de caractères laissés à gauche du texte et qui ne seront pas visibles : s'il vaut 0.3, 30 % du texte est à gauche de la zone de saisie. Le deuxième nombre est le pourcentage de texte non visible à gauche de la zone de saisie, plus le pourcentage de texte visible dans cette zone. Ici, 50 % du texte est réellement visible dans le widget (voir la figure 5.13).

 
Sélectionnez
($gauche, $droite) = $saisie->xview();
Image non disponible
Figure 5.13 : Signification de $gauche et $droite

Lorsqu'on passe un indice à xview, le texte du widget de saisie se décalera à cette position pour que le caractère à l'indice spécifié soit visible à l'extrême gauche de la zone :

 
Sélectionnez
$saisie->xview(indice);

Les autres formes de xview concernent directement le défilement du texte et sont expliquées en détail au chapitre 6 :

 
Sélectionnez
$saisie->xviewMoveto(fraction); 
$saisie->xviewScroll(nombre, quoi);

V-C. Essayez et amusez-vous !

On ne peut pas faire grand-chose d'excitant avec les widgets étiquette, mais il est conseillé de s'exercer à manipuler le widget de saisie :

  • créez une zone de saisie et une étiquette, et affichez la même information dans les deux. Lorsque vous placez un nouveau texte dans la zone de saisie, l'étiquette doit afficher ce texte en même temps ;
  • créez un formulaire de saisie d'une base de données, placez une étiquette Nom, Adresse, Ville, Code Postal, Téléphone, pour chaque zone de saisie. Ajoutez un bouton « Appliquer » qui réalisera certaines vérifications sur la cohérence des informations saisies en se fondant sur les informations attendues ;
  • créez une fenêtre comportant un widget de saisie et plusieurs boutons, chacun d'eux réalisant une action différente sur le widget de saisie. Quelques suggestions : « Remise à zéro », « Supprimer la sélection », « Défaut » (remplacement par la chaîne initiale) ;
  • créez un widget de saisie et entrez-y du texte. Placez un bouton qui, lorsqu'il est pressé, renversera la chaîne saisie.

précédentsommairesuivant

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.