Introduction à Perl/Tk

Interfaces graphiques avec Perl


précédentsommairesuivant

VIII. Le widget texte

Si l'on vous demandait à quoi peut bien servir un widget texte, vous répondriez automatiquement « à afficher du texte ». Bien que ce soit vrai, c'est un peu restrictif. Le widget texte est l'un des widgets standards les plus puissants de Perl/Tk. Il est souple, configurable, et facile à utiliser pour les tâches simples. Voici quelques exemples de cas où l'on peut l'utiliser :

  • afficher et éditer un fichier en texte pur ;
  • afficher un texte formaté à partir d'un document HTML ;
  • créer une palette de couleurs avec barre de défilement et des boutons vous permettant de modifier les couleurs ;
  • gérer du texte formaté (éventuellement avec des couleurs), sur plusieurs lignes, saisi par l'utilisateur (un mini traitement de texte) ;
  • afficher du texte, avec une coloration syntaxique ;
  • rendre « cliquables » certaines parties du texte et réaliser une action donnée lorsqu'elles sont cliquées. Cela pourrait être du HTML, ou ressembler à la démo widget (23) .

Dans un widget texte, on peut placer du texte simple ou formaté, ainsi que d'autres widgets. Un widget texte peut être utilisé avec des barres de défilement afin de permettre la visualisation de nombreuses pages d'information dans un espace réduit.

VIII-A. Création et utilisation d'un widget texte

Pour créer un widget texte, on utilise la méthode Text à partir du widget parent concerné :

 
Sélectionnez
$texte = $parent->Text( [ options ... ] )->pack;

Après avoir créé le widget texte, il y a plusieurs possibilités différentes pour le remplir. L'utilisateur peut directement y saisir son texte, ou vous pouvez utiliser la méthode insert :

 
Sélectionnez
$texte->insert('end', "Être ou ne pas être...\nLà est la question.");

La forme de base de la méthode insert prend deux paramètres. Le premier est un indice indiquant où commencer l'ajout du texte, le second est la chaîne à insérer. À la différence de la méthode insert des boîtes de liste, on ne peut utiliser un tableau comme deuxième paramètre : si vous le faites, seul le premier élément du tableau sera inséré dans le texte.

L'utilisation typique d'un widget texte consiste à lire un fichier et à le placer dans la boîte de texte au fur et à mesure qu'il est lu :

 
Sélectionnez
$texte = $mw->Scrolled("Text")->pack(); 
open (DESC_FIC, "chapitre1") || 
    die "Impossible d'ouvrir chapitre1\n"; 
while (<DESC_FIC>) { 
    $texte->insert('end', $_); 
} 
close(DESC_FIC);

Vous pouvez modifier ce programme pour qu'il affiche le fichier « à l'envers » (ligne par ligne) : il suffit de remplacer la ligne d'insertion par$texte->insert(0, $_), cela placera la dernière ligne lue en haut du widget texte au lieu de la mettre en bas.

Le widget texte peut faire beaucoup plus que simplement afficher un fichier ou deux lignes d'une réplique shakespearienne. En plus des options, on dispose également de marqueurs, d'indices, et de marques contrôlant la façon dont le contenu du widget sera affiché.

VIII-B. Options du widget texte

Les options utilisables avec la méthode Text modifient la façon dont le texte est affiché dans les widgets texte. Celles qui suivent sont communes à tous les widgets : -background, -borderwidth, -cursor, -exportselection, -foreground, -highlightbackground, -highlightcolor, -highlightthickness, -insertbackground, -insertborderwidth, -insertofftime, -insertontime, -insertwidth, -padx, -pady, -selectbackground, -selectborderwidth, -selectforeground, -setgrid, -state, -takefocus, -wrap, -xscrollcommand et -yscrollcommand.

Le chapitre 3, Le bouton de base, traite de ces options.

-background => couleur

  • Modifie la couleur de l'écran affiché derrière le texte.

-borderwidth => montant

  • Configure la largeur des bords du widget.

-cursor => nom_curseur

  • Précise le curseur qui sera affiché lorsque le pointeur de la souris est au-dessus du widget texte.

-exportselection => 0 | 1

  • Détermine si le texte sélectionné dans le widget peut aussi être utilisé par le système de fenêtrage (X Window, par exemple).

-font => nom_fonte

  • Fixe la fonte dans laquelle sera affiché le texte.

-foreground => couleur

  • Configure la couleur du texte.

-height => montant

  • Configure la hauteur du widget. Le montant par défaut est 24.

-highlightbackground => couleur

  • Configure la couleur que devra prendre le rectangle de focus placé autour du widget lorsque ce dernier n'a pas le focus clavier.

-highlightcolor => couleur

  • Configure la couleur que devra prendre le rectangle de focus placé autour du widget lorsque ce dernier a le focus clavier.

-highlightthickness => montant

  • Configure l'épaisseur du rectangle de focus placé autour du widget. Le montant par défaut est 2.

-insertbackground => couleur

  • Modifie la couleur du point d'insertion.

-insertborderwidth => montant

  • Modifie la largeur du contour du point d'insertion.

-insertofftime => millisecondes

  • Configure la durée pendant laquelle le point d'insertion reste éteint. La durée par défaut est 300.

-insertontime => millisecondes

  • Configure la durée pendant laquelle le point d'insertion reste allumé. La durée par défaut est 600.

-insertwidth => montant

  • Configure la largeur du point d'insertion.

-padx => montant

  • Ajoute des espaces supplémentaires à gauche et à droite du texte à l'intérieur du widget texte.

-pady => montant

  • Ajoute des espaces supplémentaires au-dessus et en dessous du texte à l'intérieur du widget texte.

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

  • Configure le relief du contour du widget. La valeur par défaut est 'sunken'.

-selectbackground => couleur

  • Précise la couleur de la zone placée derrière le texte sélectionné.

-selectborderwidth => montant

  • Configure la largeur du contour de la zone sélectionnée.

-selectforeground => couleur

  • Fixe la couleur du texte sélectionné.

-setgrid => 0 | 1

  • Active le maillage du widget texte. Par défaut, il est inactif.

-spacing1 => montant

  • Précise l'espace supplémentaire qui sera laissé au-dessus d'une ligne de texte commençant sur sa propre ligne. Le montant par défaut est 0.

-spacing2 => montant

  • Précise l'espace supplémentaire qui sera laissé au-dessus d'une ligne de texte après qu'elle ait été automatiquement coupée par le widget texte. Le montant par défaut est 0.

-spacing3 => montant

  • Précise l'espace supplémentaire qui sera laissé après une ligne de texte terminée par un \n. Le montant par défaut est 0.

-state => 'normal' | 'disabled'

  • Indique l'état du widget texte. La valeur par défaut est 'normal'. Si cet état est 'disabled', aucun texte ne pourra être inséré, que ce soit par l'utilisateur ou par l'application (via la méthode insert).

-tabs => liste

  • Spécifie une liste de taquets de tabulation à utiliser dans le widget texte. La liste par défaut est indéfinie (utilisation des taquets par défaut, situés tous les 8 caractères).

-takefocus => 0 | 1 | undef

  • Indique si le widget pourra obtenir le focus clavier.

-width => montant

  • Fixe la largeur en caractères du widget texte. Le montant par défaut est 80.

-wrap => 'none' | 'char' | 'word'

  • Configure le mode utilisé pour déterminer la coupure de ligne automatique. La valeur par défaut est "char".

-xscrollcommand => fct_rappel

  • Précise la fonction de rappel à utiliser lorsque le widget texte est parcouru horizontalement.

-yscrollcommand => fct_rappel

  • Précise la fonction de rappel à utiliser lorsque le widget texte est parcouru verticalement.

VIII-B-1. Fontes

L'option -font permet de modifier la fonte, et notamment la taille, du texte (voir la figure 8.1). Elle définit la fonte par défaut pour le widget entier. Celle-ci sera utilisée pour tout texte inséré sans marqueur (un marqueur permet de spécifier un formatage spécial qui s'appliquera uniquement à certaines parties du texte).

Image non disponible
Figure 8.1 : Widget texte, utilisant -font => « r16 »

L'utilisation des fontes a été traitée au chapitre 3, où l'option -font a été rencontrée pour la première fois. L'annexe C présente les nouvelles méthodes de création et de manipulation des fontes de Tk8.0.

VIII-B-2. Taille du widget

Lorsque l'on crée un widget texte, il occupe habituellement 24 lignes de haut et 80 caractères de large. Selon la façon dont vous le placez dans la fenêtre (avec pack et les options -expand et -fill, ou avec grid et -sticky => "nsew"), il pourra changer de taille en même temps que la fenêtre. Pour forcer une certaine taille, vous pouvez utiliser les options -width et -height :

 
Sélectionnez
# Widget texte de 20 caractères de large sur 10 lignes de haut 
$mw->Text(-width => 20, -height => 10)->pack;

Les valeurs associées à -width sont exprimées en nombre de caractères, tandis que celles associées à -height le sont en nombre de lignes. Le widget texte peut ne pas être de la taille exacte requise par ces options si vous forcez la fenêtre à être plus grande via la fonction minsize ($mw->minsize(400,400), par exemple), notamment si vous avez utilisé -expand => 1 et -fill => 'both' avec la méthode pack. Rappelez-vous de tout cela si ce que vous voyez à l'écran ne correspond pas à ce que vous attendiez.

VIII-B-3. Style d'un widget texte

Comme pour les autres widgets, vous pouvez modifier la façon dont sera tracé le contour d'un widget texte à l'aide des options -relief et -borderwidth. Les exemples de la figure 8.2 ne ressemblent peut-être pas à des widgets texte mais, croyez-moi, en sont bien !

Image non disponible
Figure 8.2 : Widgets texte ayant des -relief différents (montre aussi l'utilisation de -width et -height pour forcer une taille plus petite

VIII-B-4. Hauteur de l'interligne

Lorsque du texte s'affiche dans un widget texte, il peut être coupé automatiquement (word wrap) et continuer sur la ligne suivante s'il est plus long que la largeur du widget. L'espace laissé entre les lignes est défini par les options -spacingN. La figure 8.3 montre les différentes zones affectées par -spacing1, -spacing2 et -spacing3.

Image non disponible
Figure 8.3 : Effets des options -spacingN

L'option -spacing1 intervient sur l'espace laissé au-dessus d'une nouvelle ligne de texte (la première d'un paragraphe). L'option -spacing2 affecte l'espace laissé entre les lignes lors des coupures automatiques. L'option -spacing3 détermine l'espace laissé après la dernière ligne d'un paragraphe (juste après un saut de ligne explicite).

VIII-B-5. Taquets de tabulation

Les taquets de tabulation d'un widget texte sont, par défaut, placés tous les huit caractères. Chaque tabulation équivaut à huit espaces (mais n'utilise pas réellement de caractère espace). On peut remplacer ce réglage par défaut à l'aide de l'option -tabs :

 
Sélectionnez
-tabs => [qw/2 center/] # Place un taquet tous les 2 pixels 
-tabs => [2, "center"] # Idem, avec une syntaxe différente

Le paramètre passé à -tabs est une liste anonyme spécifiant les positions où placer chacun des taquets de tabulation. On peut aussi donner une valeur facultative d'alignement de chacun des taquets après sa valeur numérique (comme dans l'exemple précédent). Cela semble plus compliqué, mais ne l'est pas. Voici quelques exemples qui rendent les choses plus claires :

 
Sélectionnez
# Tous les pouces, texte centré sur le taquet 
-tabs => [qw/1i center/] 
# Taquet à 1 pouce ; à 1,5 pouce, puis tous les demi-pouces 
-tabs => [qw/1i 1.5i/]

L'alignement par défaut est "left", les autres valeurs possibles sont "right", "center" ou "numeric".

Lorsque l'on spécifie des valeurs (que ce soit en centimètres, pouces, ou pixels), elles ne se cumulent pas. La liste ["1i", "1.5i"] se traduit par « un taquet de tabulation à 1 pouce du bord gauche du widget texte, et le prochain taquet à 1,5 pouce de ce même bord gauche ». Si la liste n'est pas assez longue pour couvrir la fenêtre entière, la distance entre les deux derniers taquets spécifiés sera répétée tout au long de la ligne.

Bien sûr, le positionnement de nouveaux taquets est plutôt inutile, sauf si vous souhaitez soigner la présentation du texte ; dans la plupart des cas, vous ne vous occuperez pas de cette option.

On peut remettre les taquets de tabulation à leurs positions par défaut en affectant undef à -tabs :

 
Sélectionnez
$texte->configure(-tabs => undef);

VIII-C. Une courte pause pour un bref exemple

Avant d'aborder certaines possibilités plus complexes (et plus plaisantes) des widgets texte, étudions une utilisation complète.

Voici un court programme qui affichera le contenu d'un fichier, vous permettra de le modifier puis de le sauvegarder :

 
Sélectionnez
use Tk;
$mw = MainWindow->new;

# Crée les widgets nécessaires
$cadre = $mw->Frame->pack(
    -side => 'top',
    -fill => 'x'
);
$cadre->Label( -text => "Nom du fichier : " )->pack(
    -side   => 'left',
    -anchor => 'w'
);
$cadre->Entry( -textvariable => \$nom_fic )->pack(
    -side   => 'left',
    -anchor => 'w',
    -fill   => 'x',
    -expand => 1
);
$cadre->Button(
    -text    => "Fin",
    -command => sub { exit; }
)->pack( -side => 'right' );
$cadre->Button(
    -text    => "Sauvegarder",
    -command => \&sauve_fic
)->pack(
    -side   => 'right',
    -anchor => 'e'
);
$cadre->Button(
    -text    => "Charger",
    -command => \&lire_fic
)->pack(
    -side   => 'right',
    -anchor => 'e'
);
$mw->Label(
    -textvariable => \$info,
    -relief       => 'ridge'
)->pack(
    -side => 'bottom',
    -fill => 'x'
);
$texte = $mw->Scrolled("Text")->pack(
    -side   => 'bottom',
    -fill   => 'both',
    -expand => 1
);

MainLoop;

# lire_fic vérifie quel est le nom du fichier et le charge
sub lire_fic {
    $info = "Chargement du fichier '$nom_fic'...";
    $texte->delete( "1.0", "end" );
    if ( !open( FIC, "$nom_fic" ) ) {
        $t->insert( "end", "ERREUR : Impossible d'ouvrir $nom_fic\n" );
        return;
    }
    while (<FIC>) { $texte->insert( "end", $_ ); }
    close(FIC);
    $info = "Fichier '$nom_fic' chargé.";
}

# sauve_fic sauvegarde le fichier en utilisant le nom placé
# dans la zone de saisie
sub sauve_fic {
    $info = "Sauvegarde de '$nom_fic";
    open( FIC, ">$nom_fic" );
    print FIC $texte->get( "1.0", "end" );
    $info = "Fichier '$nom_fic' sauvegardé.";
}

La figure 8.4(24) montre la fenêtre obtenue lorsqu'un fichier a été chargé et sauvegardé.

Image non disponible
Figure 8.4 : Un simple éditeur de texte, contenant 'monfichier'

VIII-D. Indices de texte

Lorsque nous avons parlé des valeurs d'indices pour les boîtes de liste, chaque indice faisait référence à une ligne de la liste. La première ligne était à l'indice 0, etc. Dans le cas d'un widget texte, l'indice peut désigner une ligne précise ou l'un de ses caractères. Un indice de widget texte est construit en utilisant un indice de base, suivi éventuellement d'un modificateur. L'ensemble indice, base et modificateur, doit être placé entre apostrophes doubles.

VIII-D-1. Valeurs de l'indice de base

"n.m"

  • Ce format vous permet de spécifier explicitement un numéro de ligne et un numéro de caractère dans cette ligne. Les lignes commencent à l'indice 1 (ce qui est différent du widget liste), et les caractères débutent à la position 0.

"@x,y"

  • Désigne le caractère le plus près des coordonnées x, y dans le widget.

"end"

  • La fin du widget texte, après le dernier caractère \n.

"mark"

  • Désigne le caractère situé après l'emplacement appelé mark. Les deux marques fournies par Tk sont "current" et "insert". Ce qu'elles désignent sera expliqué plus loin dans ce chapitre.

"marqueur.first"

  • Un marqueur (tag , en anglais) remplace simplement certaines instructions de formatage spéciales (étudiées dans la section suivante). Après avoir créé des marqueurs, vous pouvez utiliser cette forme d'indice. marqueur.first est le premier caractère de type marqueur du widget texte. Vous pourriez, par exemple, créer un marqueur "titre" et utiliser l'indice "titre.first".

"marqueur.last"

  • Désigne le caractère placé immédiatement après le texte marqué par marqueur.

$widget

  • Si vous avez un widget contenu dans le widget texte, vous pouvez désigner son emplacement à l'aide de la variable qui le décrit.

$image

  • À partir de Tk8.0, vous pouvez intégrer des images dans un widget texte. Désigner l'emplacement d'une telle image est alors possible via la variable qui la décrit.

VIII-D-2. Modificateurs d'indices

On peut utiliser des modificateurs d'indices après une valeur d'indice de base.

[ + | - ] nombre [ chars | lines ]

  • On peut utiliser + et - pour additionner/soustraire des lignes et des caractères à un indice de base. L'indice "end - 1 lines" désigne le texte placé sur la ligne avant "end". Faites bien attention lorsque vous utilisez ce modificateur, car toutes les lignes comptent aussi comme une ligne complète.

linestart

  • Modifie l'indice afin de désigner le premier caractère de cette ligne. Ainsi, $texte->insert("end linestart", $chaine) insérera la ligne devant la dernière ligne du widget texte. insert placera le nouveau texte avant l'indice fourni.

lineend

  • Désigne le dernier caractère de la ligne (habituellement, le caractère de retour à la ligne). Ce modificateur est utile lorsque l'on ne connaît pas le nombre exact de caractères d'une ligne, mais que l'on veut ajouter du texte à la fin de celle-ci.

wordstart

  • Ajuste l'indice pour qu'il désigne le premier caractère du mot pointé par l'indice de base.

wordend

  • Ajuste l'indice pour qu'il désigne le caractère placé après la fin du mot pointé par l'indice de base.

VIII-D-3. Exemples d'indices de texte

"end"

  • La position juste après la dernière ligne de texte du widget, quel que soit le volume de texte dans celui-ci.

"1.0"

  • Le premier caractère de la première ligne du widget texte. Le 1 représente la ligne et le 0, le caractère.

"2.0 - 1 chars"

  • Le dernier caractère de la première ligne. On le désigne à l'aide du premier caractère de la deuxième ligne (2.0) et en ôtant un caractère à cette position. Si l'on utilise la méthode insert avec cet indice, cela insérerait le texte juste avant le \n à la fin de la première ligne.

"1.end"

  • Désigne aussi le dernier caractère de la première ligne, mais de façon plus simple.

"2.0 lineend"

  • La fin de la deuxième ligne. Il est nécessaire de préciser 2.0, et pas simplement 2 car cette dernière valeur n'est pas un indice de base correct.

Les indices de base sont faciles à comprendre, mais tout se complique lorsque l'on commence à faire de l'arithmétique avec les indices. Il suffit de se rappeler que l'on désigne une position dans le widget texte, et que cette position peut changer si du texte est inséré ou supprimé (soit par l'utilisateur, soit par l'application).

Bien que certaines combinaisons puissent sembler stupides ("1.0 linestart", par exemple), pensez qu'il est possible que vous appeliez des méthodes renvoyant des informations peu précises sur un événement. Si, par exemple, un utilisateur clique dans le widget texte et presse un bouton qui augmentera la taille de la fonte de la ligne entière, l'arithmétique des indices vous permettra de désigner toute cette ligne sans même connaître avec certitude son emplacement.

VIII-E. Marqueurs de texte

Les marqueurs de texte vous offrent un autre moyen d'accéder à des parties du texte du widget. Un marqueur sert trois objectifs et le même marqueur peut être utilisé pour tous, ou pour un seul :

  • associer des informations de formatage à une partie (ou à des parties) du texte ;
  • associer une liaison à du texte dans le widget ;
  • gérer le texte sélectionné.

Les marqueurs servent aussi à modifier l'apparence du texte à l'écran : la fonte, la taille, la couleur et l'espacement sont quelques-unes des propriétés du texte affectées par les marqueurs. On peut modifier ces propriétés en créant ses propres marqueurs (avec leur propre nom) et en utilisant des paires option/valeur pour introduire des informations de formatage. En plus de la modification du format, les marqueurs servent à appliquer une liaison spécifique (telle que l'exécution d'une tâche lorsque l'utilisateur clique sur ce texte). Un marqueur spécial, "sel", gère le texte sélectionné : à chaque fois que l'utilisateur sélectionne du texte, l'emplacement de celui-ci est marqué avec le marqueur "sel".

Tout texte contenu dans un widget texte peut avoir un ou plusieurs marqueurs qui lui sont associés. Si l'on applique deux marqueurs au même morceau de texte et qu'ils modifient tous deux la fonte, le dernier marqueur appliqué prédomine.

VIII-E-1. Options des marqueurs

Les options permettant de configurer du texte marqué sont quasiment un sous-ensemble des options de configuration du widget texte lui-même. Certaines options ne concernent que du texte marqué.

-background => couleur

  • Configure la couleur de la zone située derrière le texte.

-bgstipple => motif

  • Précise le motif utilisé pour tracer la zone derrière le texte. Cette option permet de donner un aspect ombré.

-borderwidth => montant

  • Configure la largeur du relief tracé autour du texte ligne par ligne.

-fgstipple => motif

  • Précise le motif utilisé pour tracer le texte.

-font => nom_fonte

  • Indique la fonte qui sera utilisée par le texte.

-foreground => couleur

  • Configure la couleur du texte.

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

  • Établit la position du texte dans le widget.

-lmargin1 => montant

  • Précise l'indentation des premières lignes de paragraphes à partir du bord gauche du widget.

-lmargin2 => montant

  • Précise l'indentation des lignes de paragraphes (sauf la première) à partir du bord gauche du widget. Parfois appelé « paragraphes en retrait ».

-offset => montant

  • Précise le nombre de pixels duquel le texte sera surélevé ou abaissé par rapport à la ligne de référence. Cette option peut servir à créer des indices et des exposants.

-overstrike => 0 | 1

  • Si cette option est vraie, le texte sera barré par une ligne.

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

  • Détermine la façon dont sera tracé le contour du texte, ligne par ligne.

-rmargin => montant

  • Précise l'espace qui sera laissé entre le texte et le bord droit du widget.

-spacing1 => montant

  • Précise le supplément d'espace laissé au-dessus d'une ligne de texte commençant sa propre ligne. Par défaut, montant vaut 0.

-spacing2 => montant

  • Précise le supplément d'espace laissé au-dessus d'une ligne de texte après qu'elle a été coupée automatiquement par le widget. Par défaut, montant vaut 0.

-spacing3 => montant

  • Précise le supplément d'espace laissé après une ligne terminée par un \n. Par défaut, montant vaut 0.

-tabs => liste

  • Indique l'ensemble des taquets de tabulation pour ce texte. Consultez la section consacrée aux taquets de tabulation, plus haut dans ce chapitre, pour plus d'informations.

-underline => booléen

  • Indique si le texte doit être souligné.

-wrap => 'none' | 'char' | 'word'

  • Détermine le mode dans lequel le texte sera coupé. 'none' signifie que les lignes plus longues que le widget n'est large ne seront pas coupées. 'char' coupera sur tout caractère, tandis que 'word' ne coupera qu'entre les mots.

VIII-E-2. Un exemple de marqueur simple

Voici un exemple montrant comment créer un marqueur simple et comment l'utiliser

pour insérer du texte dans un widget texte (l'écran obtenu est montré en figure 8.5 :

 
Sélectionnez
$texte = $mw->Text()->pack();
$texte->tagConfigure( 'gras', -font => "-*-Courier-Bold-B-Normal--*-120-*-*-*-*-*-*" );

# Utilisez -font => "{Courier New} 24 {bold}" pour les systèmes Win32
$texte->insert( 'end', "Voici du texte normal\n" );
$texte->insert( 'end', "Voici du texte en gras\n", 'gras' );

La première ligne crée le widget texte et le place à l'écran.

La ligne 2 crée le marqueur 'gras'. Ne soyez pas troublé par l'utilisation du mot « configure » au lieu de « create ». Lorsque l'on configure un marqueur, on le crée aussi. Ici, 'gras' est associé à une fonte différente (la même que celle par défaut sous Unix, mais en gras).

Jusqu'à maintenant, nous n'avons encore rien modifié dans le widget texte. Nous avons simplement fait en sorte de pouvoir utiliser le marqueur plus loin dans le code. N'importe quel nom de marqueur convient, tant qu'il s'agit d'une chaîne correcte. On aurait pu choisir « texte_en_gras » ou « fonte_en_gras », ou « marqueur1 ». Si vous utilisez un style de programmation correct (et que vous souhaitez pouvoir maintenir votre code), utilisez un nom indiquant à quoi sert le marqueur.

La troisième ligne insère du texte dans le widget.

La ligne 4 insère du texte supplémentaire, en utilisant le marqueur 'gras'. La méthode insert permet de spécifier un marqueur en tant que troisième paramètre ; la chaîne sera insérée dans le widget et associée au marqueur spécifié. Le marqueur 'gras' a été configuré pour modifier la fonte ; par conséquent, tout texte avec le marqueur 'gras' s'affichera dans la fonte associée à celui-ci.

Image non disponible
Figure 8.5 : Widget texte avec du texte normal et en gras

Il s'agit ici d'un exemple très simplifié. Que faire, si l'on désire modifier le texte saisi par l'utilisateur ? Dans ce cas, on ne peut utiliser la méthode insert, mais on se servira de la méthode tagAdd :

 
Sélectionnez
$texte->tagAdd('gras', '1.0', 'end');

Cette ligne applique le marqueur 'gras' à tout le texte du widget.

VIII-E-3. Utilisation du marqueur "sel" pour manipuler la sélection

Le marqueur "sel" est un marqueur spécial, géré par le widget texte. Tout texte sélectionné par l'utilisateur se verra affecter ce marqueur. On peut aussi forcer la sélection en utilisant certaines méthodes propres aux marqueurs (méthodes dont nous n'avons pas encore traité) afin de placer "sel" sur un texte donné. Pour sélectionner, par exemple, la troisième ligne du texte :

 
Sélectionnez
$texte->tagAdd("sel", "3.0", "3.0 lineend");

Voici un exemple montrant comment ajouter un autre marqueur au texte actuellement sélectionné :

 
Sélectionnez
$texte->tagAdd('gras', 'sel.first', 'sel.last') 
    if ($texte->tagRanges('sel'));

Lorsque l'on utilise le marqueur "sel" comme partie d'un indice, on doit d'abord s'assurer que le marqueur existe dans le widget texte (à l'aide de tagRanges), ou l'on obtiendra une énorme erreur.

VIII-E-4. Création et configuration des marqueurs

La première action sur un marqueur consiste à le créer à l'aide de tagConfigure (sauf si vous utilisez le marqueur "sel", créé automatiquement). Le premier paramètre de tagConfigure est le nom du marqueur et les autres (qui sont facultatifs) sont les paires option/valeur décrites à la section précédente. Voici quelques exemples :

 
Sélectionnez
# Création d'un marqueur sans option
$texte->tagConfigure("special"); 
# Création d'un marqueur qui modifiera la couleur 
$texte->tagConfigure("bleu", -foreground => "blue"); 
# Création d'un marqueur qui soulignera le texte 
$texte->tagConfigure("souligne", -underline => 1); 
# Création d'un marqueur changeant la couleur et l'espacement 
$texte->tagConfigure("grand_bleu", 
    -foreground => "blue", 
    -spacing2   => 6
);

On peut modifier la configuration d'un marqueur déjà créé en utilisant tagConfigure une seconde fois. Tous les changements effectués sur le marqueur affectent immédiatement tout texte ayant ce marqueur dans le widget :

 
Sélectionnez
# Ajoute une couleur de fond à "bleu" 
$texte->tagConfigure("bleu", -background => "red"); 
# Modifie l'espacement de "grand_bleu" 
$texte->tagConfigure("grand_bleu", -spacing2 => 12);

Comme avec les méthodes configure des widgets, on peut utiliser tagConfigure pour récupérer la configuration courante d'un marqueur donné. Pour obtenir toutes les options d'un marqueur, ainsi que leur valeur sous la forme d'une liste de listes :

 
Sélectionnez
@liste_de_listes = $texte->tagConfigure("bleu"); 
foreach $opt (@liste_de_listes) { print "@$opt\n"; } # l'affiche

Chaque sous-liste contient cinq éléments, dont le nom de l'option et sa valeur. On peut aussi limiter à une seule option l'information à récupérer :

 
Sélectionnez
@liste = $texte->tagConfigure("bleu", -font);

On utilisera tagCget si l'on souhaite connaître la valeur d'une option particulière :

 
Sélectionnez
$valeur = $texte->tagCget("grand_bleu", -spacing2);

VIII-E-5. Ajout d'un marqueur à du texte existant

Nous avons déjà vu un exemple d'utilisation de la méthode tagAdd : elle permet d'ajouter un marqueur à des parties du texte dans le widget. Son utilisation est la suivante :

 
Sélectionnez
$texte->tagAdd('nom_marqueur', début1 [, fin1, début2, fin2, ... ] )

On peut ajouter un marqueur à un simple indice ou à un intervalle d'indices ; cela signifie que l'on peut ajouter un marqueur au widget texte à plusieurs endroits simultanément. Supposons que vous vouliez ajouter le marqueur entete aux lignes 1, 12 et 30, car il s'y trouve des titres de sections que vous voulez mettre en évidence par rapport au reste du texte. La ligne tagAdd ressemblerait alors à ceci :

 
Sélectionnez
$texte->tagAdd('entete', '1.0',  '1.0 lineend', 
                         '12.0', '12.0 lineend', 
                         '30.0', '30.0 lineend');

Supposons maintenant que le formatage de 'entete' agrandisse la fonte : les lignes concernées s'affichent maintenant différemment du reste du texte dans le widget.

Vous pouvez ajouter plus d'un marqueur à une section de texte. Il est possible, par exemple, d'avoir à la fois les marqueurs 'entete' et 'couleur'. Si les deux marqueurs modifient la même option (-font, par exemple), la dernière configuration de cette option l'emporte, sauf si la priorité du marqueur a été modifiée à l'aide de tagRaise ou tagLower.

Lorsque l'on affecte un marqueur à un ensemble de texte, tout ce qui sera inséré entre les indices de début et de fin de ce texte se verra automatiquement affecté par ce marqueur ; que l'on utilise insert sans marqueur spécifique, ou que le texte soit saisi dans le widget par l'utilisateur. Si l'on spécifie un marqueur avec insert, ce marqueur surcharge celui affecté au texte environnant.

VIII-E-6. Utilisation de bind avec les marqueurs

L'une des principales raisons d'utiliser des marqueurs est qu'ils permettent d'assigner une liaison à certaines parties du texte. Après avoir créé un marqueur à l'aide de tagConfigure, vous pouvez utiliser bind pour qu'une fonction de rappel s'exécute lorsqu'une certaine séquence d'événements (un clic souris, par exemple) intervient sur ce texte marqué. Avec les widgets bouton, nous avions une liaison par défaut entre <Button-1> (le bouton gauche de la souris) et la fonction de rappel associée à l'option -command. On peut faire la même chose avec du texte marqué.

Le meilleur exemple est l'utilisation du texte comme un lien hypertexte, comme c'est le cas sur le Web. Lorsque l'on clique sur le lien, quelque chose se passe : un nouveau document se charge ou une autre fenêtre est créée et présentée à l'utilisateur. La forme classique d'un appel à tagBind est la suivante :

 
Sélectionnez
$texte->tagBind(nom_marqueur [, séquence, fct_rappel ] )

La fonction de rappel est identique à celle que l'on indique à l'option -command d'un bouton. La séquence est une description de l'événement qui déclenche le script. Les seules séquences que l'on peut indiquer sont celles qui ont un rapport avec la souris ou le clavier (voir le chapitre 14, Liaisons d'événements, pour plus de détails sur les événements disponibles).

Le code suivant montre un exemple de « pseudo-lien ». Tout ce que fait le lien, lorsque l'on clique sur lui, est de montrer la fin du widget texte :

 
Sélectionnez
$texte = $mw->Scrolled( "Text", -width => 40 )->pack(
    -expand => 1,
    -fill   => 'both'
);
$texte->tagConfigure( 'fin', -underline => 1, -foreground => 'red' );
$texte->tagBind( 'fin', "<Button-1>", sub { shift->see('end'); } );

# Mise en place des liaisons pour modifier le curseur
# lorsqu'il est sur cette ligne
$texte->tagBind( 'fin', "<Any-Enter>", sub { shift->configure( -cursor => 'hand2' ) } );
$texte->tagBind( 'fin', "<Any-Leave>", sub { shift->configure( -cursor => 'xterm' ) } );
$texte->insert( 'end', "FIN\n", "fin" );

# Insertion de quelques lignes
for ( $i = 1 ; $i <= 100 ; $i++ ) {
    $texte->insert( 'end', "$i\n" );
}

Dans les sub des appels à tagBind, on utilise l'instruction shift afin d'invoquer une méthode. On peut procéder ainsi, car le premier paramètre envoyé implicitement à la fonction de rappel de bind est le widget texte. Quel que soit le widget sur lequel tagBind est invoquée, c'est lui qui sera envoyé comme premier paramètre à la fonction de rappel. Pour utiliser plus d'une fois le widget dans la fonction de rappel, il suffit de l'assigner à une variable locale en faisant, par exemple, my $widget = shift.

Si l'on a créé le widget texte dans la portée globale du programme et que l'on a placé une référence à ce widget dans la variable $texte, on peut aussi y accéder dans la fonction de rappel en utilisant cette variable. Cela n'est possible que parce que $texte est de portée globale et qu'elle est donc visible par la fonction de rappel. Si l'on souhaite associer la même fonction à deux widgets texte différents, il faut utiliser shift pour obtenir le widget correct :

 
Sélectionnez
$texte1->tagBind('fin', "<Button-1>", \&goto_fin ); 
$texte2->tagBind('fin', "<Button-1>", \&goto_fin ); 
sub goto_fin { 
    my $texte = shift; 
    $texte->see('end'); 
}

L'utilisation d'une même fonction de rappel pour les deux widgets vous permet d'économiser des lignes de code dans votre programme.

Pour déterminer quelles sont les liaisons d'un marqueur, il suffit d'utiliser tagBind en lui passant uniquement son nom en paramètre :

 
Sélectionnez
@liaisons = $texte->tagBind("marqueur");

La liste obtenue sera vide si le marqueur n'a aucune liaison au moment de cet appel.

VIII-E-7. Suppression de toutes les instances d'un marqueur

La méthode tagDelete permet de supprimer un marqueur déjà créé :

 
Sélectionnez
$texte->tagDelete(marqueur1 [ ,marqueur2 . . .] )

Cette méthode supprime complètement les marqueurs ; cela signifie que le texte reprend sa configuration par défaut et que toutes les liaisons ou autres informations associées à ces marqueurs sont aussi détruites.

tagDelete peut aussi être utilisée lorsque vous créez dynamiquement des marqueurs temporaires dans votre programme et que vous devez les détruire ensuite, lorsque les informations ne sont plus correctes.

VIII-E-8. Annulation de l'effet d'un marqueur

Pour ôter un marqueur d'un bloc de texte précis, on utilise la méthode tagRemove :

 
Sélectionnez
$texte->tagRemove(marqueur, début1 [ , fin1, début2, fin2, ...] );

On indique le nom du marqueur et un indice ou intervalle d'indices duquel supprimer le marqueur qui reste intact : il est simplement ôté du texte indiqué par les indices.

VIII-E-9. Priorités des marqueurs

Lorsque plusieurs marqueurs agissent sur le même texte, le dernier appliqué surcharge les précédents ; ses options de configuration sont prioritaires. On peut modifier la priorité des marqueurs en utilisant les méthodes tagLower et tagRaise :

 
Sélectionnez
$texte->tagRaise(marqueur [, marqueur_sup]); 
$texte->tagLower(marqueur [, marqueur_inf ] );

Ces méthodes prennent un nom de marqueur en premier paramètre. S'il n'a pas d'autre paramètre, le premier marqueur reçoit la priorité la plus haute (tagRaise) ou la plus basse (tagLower). Ceci concerne tout le texte du widget texte, quel que soit l'endroit où les marqueurs s'appliquent. Si un deuxième marqueur est indiqué, le premier est placé avant (tagRaise) ou après le deuxième marqueur.

Cela fait penser à une réorganisation de la pile des marqueurs (s'appliquant tous au même texte). Le marqueur au sommet est celui qui a le plus à dire, et s'il a une option -foreground valant 'red', alors tout le texte ayant ce marqueur sera rouge, quelle que soit la valeur de -foreground pour les autres marqueurs. Si l'on utilise tagRaise pour mettre au sommet un marqueur ayant la valeur 'blue' pour cette option, le texte marqué changera de couleur pour s'afficher en bleu.

VIII-E-10. Obtention des noms de marqueurs

On peut retrouver tous les différents marqueurs s'appliquant à un indice donné, ou à tout le texte, en utilisant la méthode tagNames :

 
Sélectionnez
$texte->tagNames([ indice ] )

Si l'on donne un indice, la liste renvoyée ne contiendra que les marqueurs qui s'y appliquent. Sinon, la liste contiendra tous les marqueurs ayant un rapport avec le widget texte, qu'ils s'appliquent ou non au texte du widget.

VIII-E-11. Déterminer où s'applique un marqueur

Si l'on connaît le nom d'un marqueur, on peut trouver où il s'applique dans le widget texte à l'aide des méthodes range. La première, tagRanges, renvoie une liste contenant des paires d'indices pour l'ensemble du widget :

 
Sélectionnez
@liste = $texte->tagRanges("marqueur"); 
# renvoie ( début1, fin1, début2, fin2 ...)

S'il n'y a pas de texte ayant ce marqueur dans le widget, la liste sera vide.

On peut aussi obtenir une par une les paires d'indices à l'aide de la méthode tagNextrange :

 
Sélectionnez
($debut, $fin) = $texte->tagNextrange("marqueur", début [ , fin ] );

La recherche de "marqueur" débutera à début et ne dépassera jamais fin. Si ce dernier n'est pas précisé, la recherche continuera jusqu'au marqueur ou stoppera à la fin du widget texte.

VIII-F. Insertion de texte

Maintenant que nous avons étudié les indices et les marqueurs de texte, nous pouvons détailler des méthodes de manipulation du contenu du widget.

Comme nous l'avons vu dans les nombreux exemples de ce chapitre, nous plaçons du texte dans le widget à l'aide de insert. Le premier paramètre est un indice précisant où le texte sera inséré. Le deuxième paramètre est la chaîne à placer. Le suivant, facultatif, est un nom de marqueur unique ou une liste de marqueurs à affecter au texte inséré. Voici le mode d'utilisation de insert :

 
Sélectionnez
$texte->insert(indice, chaîne 
    [ , liste_marqueurs, chaîne, liste_marqueurs ...] ) ;

Jusqu'à maintenant, nous n'avons utilisé que des marqueurs uniques. Si l'on souhaite indiquer plus d'un marqueur, il suffit de placer leurs noms entre crochets, afin de créer une liste :

 
Sélectionnez
$texte->insert('end', "Voici une ligne très marquée", 
    ['marqueur1', 'marqueur2', 'marqueur3']);

Pour utiliser plusieurs ensembles de marqueurs, on peut fournir d'autres lignes de texte et des listes de marqueurs supplémentaires :

 
Sélectionnez
$texte->insert( 'end', "Ceci est l'entête", [ 'entete', 'souligne' ], "Deuxième ligne", [ 'gras', 'bleu' ] );

Lorsque l'on utilise la méthode insert pour insérer plus d'une ligne de texte avec plusieurs marqueurs, on doit fournir des couples : texte, marqueurs, texte, marqueurs, etc. Si le marqueur utilisé n'est pas défini (avec tagConfigure), le texte ne sera pas affecté, mais le marqueur lui sera quand même assigné. Si on le désire, on peut créer le marqueur plus tard.

VIII-G. Suppression de texte

Pour supprimer du texte du widget, on utilise la méthode delete :

 
Sélectionnez
$texte->delete(début [ , fin ] );

Le premier indice est nécessaire, le deuxième facultatif. Si les deux sont fournis, le premier indice doit être inférieur ou égal au second. Tous les caractères entre début et fin (fin non compris) sont supprimés du widget. Pour tout ôter du widget, il suffit de faire $texte->delete("1.0", 'end').

VIII-H. Capture de texte

On utilisera beaucoup la méthode get : elle renvoie le texte situé entre début et fin. Si fin n'est pas précisé, seul le caractère placé à l'indice début est renvoyé. L'utilisation de get est la suivante :

 
Sélectionnez
$t = $text->get(début [ , fin ] );

Comme dans tout intervalle d'indice, début doit être inférieur ou égal à fin, ou une chaîne vide sera renvoyée.

VIII-I. Conversion des valeurs d'indices

Lorsque l'on travaille avec des indices, il est utile de pouvoir convertir une forme d'indice compliquée en une forme plus simple. La méthode index renvoie un indice sous la forme ligne.car :

 
Sélectionnez
$nouvelle_valeur = $texte->index(indice);

La valeur indice peut être n'importe quelle expression correcte d'un indice.

VIII-J. Comparaison d'indices

La méthode compare permet de comparer deux indices :

 
Sélectionnez
$texte->compare(indice1, op, indice2 );

Les paramètres sont : le premier indice, l'opération de test à réaliser et le deuxième indice. Les valeurs possibles de op sont « < », « <= », « == », « > », « >= » et « != ». Cette méthode renvoie 1 si le test est vérifié, 0 sinon. L'appel

 
Sélectionnez
$etat = $texte->compare("1.0", "<=", "end");

renvoie 1, car l'indice « 1.0 » est inférieur ou égal à "end".

VIII-K. Affichage du texte situé à un indice

La méthode see force le widget à afficher la partie du texte contenant l'indice spécifié :

 
Sélectionnez
$texte->see(indice);

À la suite de cet appel, le texte du widget défilera vers le haut ou vers le bas. Si l'indice était déjà visible, rien ne se passera.

VIII-L. Obtention de la taille d'un caractère

La méthode bbox renvoie une liste de quatre éléments décrivant la boîte autour du caractère situé à l'indice indiqué :

 
Sélectionnez
($x, $y, $l, $h) = $texte->bbox(indice);

Les deux premiers éléments renvoyés sont les coordonnées x et y du coin supérieur gauche. Les deux derniers sont la largeur et la hauteur de la boîte. La boîte de dimensionnement décrit seulement la partie visible du caractère : s'il est à moitié caché ou invisible, les valeurs renvoyées refléteront cet état de fait.

VIII-M. Obtention d'informations sur une ligne

La méthode dlineinfo renvoie une liste de cinq éléments. Ceux-ci décrivent la partie de la ligne contenant l'indice indiqué :

  • abscisse du coin supérieur gauche ;
  • ordonnée du coin supérieur gauche ;
  • largeur de la zone ;
  • hauteur de la zone ;
  • position de la ligne de référence de la ligne, mesurée à partir de l'abscisse contenue dans le premier élément.

Voici un exemple d'utilisation :

 
Sélectionnez
($x, $y, $l, $h, $base) = $texte->dlineinfo("indice");

À la différence de la méthode bbox, même les zones non visibles (dues aux mots non coupés) sont utilisées dans les calculs tant qu'une partie de la ligne est visible. Cependant, si la ligne n'est pas visible du tout, la liste sera vide. Si la ligne est coupée en plusieurs lignes, la zone complète sera utilisée.

VIII-N. Recherche dans un widget texte

On utilise la méthode search pour chercher un motif ou expression rationnelle dans le widget texte. Cette méthode prend comme paramètres des options éventuelles, le motif à rechercher et un indice indiquant où commencer la recherche :

 
Sélectionnez
$indice = $texte->search([options], motif, début [ , fin ] );

Si une correspondance est trouvée, l'indice renvoyé pointera sur le premier caractère de celle-ci. Si rien n'est trouvé, la méthode renverra une chaîne vide.

Les options reconnues sont :

-forwards

  • Demande à search de rechercher « vers l'avant » du widget texte en commençant à l'indice indiqué. C'est l'option par défaut.

-backwards

  • Demande à search de rechercher « vers l'arrière » du widget texte en commençant au caractère précédant l'indice indiqué.

-exact

  • Le motif doit correspondre exactement au texte. C'est le comportement par défaut.

-regexp

  • Le motif sera considéré comme une expression rationnelle.

-nocase

  • Ignore les différences de casse entre motif et le texte du widget.

-count => variable

  • variable est un pointeur vers une variable (i.e. \$variable). Le nombre de caractères reconnus y sera stocké.

--

  • Cette option ne fait rien, si ce n'est forcer le prochain paramètre à être considéré comme un motif, même si la chaîne suivante débute par « - ».

Voici un exemple simple d'utilisation de search :

 
Sélectionnez
$resultat = $texte->search(-backwards, "trouve-moi", 'end'); 
$emplacement = $texte->search(-nocase, "OPTIONS", "1.0");

VIII-O. Barres de défilement

Un widget texte peut être parcouru horizontalement et verticalement, il dispose donc des méthodes xview et yview. Celles-ci sont décrites au chapitre 6, Barres de défilement.

VIII-P. Marques

Il existe plusieurs moyens de désigner différentes positions tout au long d'un widget texte. Les indices font référence à un caractère, les marqueurs sont des références nommées à un seul ou à plusieurs caractères. Le terme « marque » permet de faire référence aux espaces entre les caractères. Comme les marqueurs, les marques ont un nom. La marque "insert", par exemple, désigne la position du point d'insertion. Cependant, les marqueurs font référence à des caractères réels et, si ceux-ci sont détruits, le marqueur ne leur est plus associé. Une marque reste en place, que les caractères qui l'entourent soient supprimés ou que d'autres soient ajoutés. Les marques ne peuvent désigner qu'un seul emplacement du widget à la fois.

Une fois créée, une marque est utilisable comme un indice. Le pôle d'attraction de la marque décidera du côté où le texte sera inséré. Si cette attraction vaut 'right' (c'est sa valeur par défaut), le texte sera inséré à gauche de la marque, car celle-ci est soudée au caractère à sa droite. Si l'attraction vaut 'left', le texte sera inséré à droite de la marque et celle-ci désignera la gauche du dernier caractère inséré. Avec cette valeur, le texte semble être inséré à l'envers.

Le widget texte place automatiquement deux marques spéciales : "insert" et "current". La première est la position du point d'insertion, où qu'il se trouve. La seconde est la position la plus proche de la souris et se modifie lorsque cette dernière est déplacée (tant que son bouton n'est pas pressé). Les deux marques sont gérées de façon interne et ne peuvent être détruites.

Vous verrez aussi une marque nommée "anchor" apparaissant dans la liste renvoyée par la méthode markNames lorsque l'on clique dans le widget texte. Cette marque a toujours la même valeur d'indice que la marque "insert", mais elle peut ne pas exister.

VIII-P-1. Configuration et obtention du pôle d'attraction d'une marque

La méthode markGravity permet de configurer le pôle d'attraction d'une marque :

 
Sélectionnez
$texte->markGravity(marque [ , direction ] );

Les valeurs possibles de direction sont "right" et "left". L'attraction par défaut d'une nouvelle marque est "right". Si l'on ne précise pas d'attraction, cette méthode renvoie l'attraction actuelle de cette marque.

VIII-P-2. Noms des marques

La méthode markNames permet de récupérer une liste de toutes les marques du widget texte :

 
Sélectionnez
@noms = $texte->markNames();

Cette méthode ne prend aucun paramètre et renvoie une liste. Voici un exemple montrant comment énumérer les marques se trouvant dans un widget texte :

 
Sélectionnez
$mw->Button(
    -text    => "Rapport",
    -command => sub {
        my @marques = $texte->markNames();
        foreach (@marques) {
            print "MARQUE : $_ à ", $texte->index($_), "\n";
        }
    }
)->pack( -side => 'left' );

Lorsque l'on clique dans la fenêtre pour positionner le point d'insertion, on obtient les messages suivants :

 
Sélectionnez
MARQUE : insert à 2.15 
MARQUE : anchor à 2.15 
MARQUE : current à 3.0

VIII-P-3. Création et suppression de marques

La méthode markSet permet de créer une marque et de la fixer à un certain indice :

 
Sélectionnez
$texte->markSet(marque, indice);

En plus de la marque que vous souhaitez créer, précisez l'indice où placer celle-ci. Si, par exemple, vous voulez pouvoir toujours insérer à la fin de la ligne 3 :

 
Sélectionnez
$texte->markSet("fin de la ligne 3", "3.0 lineend"); 
... 
$texte->insert("fin de la ligne 3", "texte à insérer");

La méthode markUnset ôte la marque du widget texte et la supprime définitivement. Elle n'apparaîtra plus dans la liste renvoyée par markNames et elle ne pourra plus, non plus, servir de valeur d'indice. On peut donner plus d'une marque en paramètre de markUnset :

 
Sélectionnez
$texte->markUnset(marque1 [ , marque2, marque3 ... ] );

VIII-Q. Imbrication de widgets

L'une des possibilités les plus intéressantes des widgets texte est que l'on peut y placer d'autres widgets (tels que des boutons ou des zones de saisie). L'avantage des widgets imbriqués est que l'on peut créer un ensemble de widgets muni d'une barre de défilement, chacun d'eux étant sur une ligne distincte.

Avant de passer en revue les différentes fonctions disponibles pour gérer l'incorporation de widgets, étudions un court exemple : dans un programme, on souhaite souvent faire beaucoup de saisies de données, ce qui signifie que l'on a besoin de beaucoup de widgets étiquettes et de zones de saisie. Il y en a parfois trop pour les placer tous à l'écran sans désorganiser la fenêtre. En utilisant un widget texte avec barre de défilement et en y plaçant les étiquettes et les zones de saisie, on peut créer bien plus de widgets dans bien moins d'espace. Voici le code :

 
Sélectionnez
use Tk;
my %info;    # stockage des informations recueillies
$mw = MainWindow->new;
$mw->title("Zones de saisie");
$cadre = $mw->Frame->pack( -side => 'bottom' );
$cadre->Button(
    -text    => "Fin",
    -command => sub { exit; }
)->pack( -side => 'left' );
$cadre->Button(
    -text    => "Sauver",
    -command => sub {       # faire quelque chose de %info;
    }
)->pack( -side => 'bottom' );
$texte = $mw->Scrolled(
    "Text",
    -width => 40,
    -wrap  => 'none'
)->pack(
    -expand => 1,
    -fill   => 'both'
);

foreach (
    qw/Nom Adresse Ville Code-postal Téléphone Emploi
    Société Activité_Adresse Téléphone-bureau/
  )
{
    $champ = $texte->Label(
        -text   => "$_ :",
        -relief => 'groove',
        -width  => 20
    );
    $texte->windowCreate( 'end', -window => $champ );
    $champ = $texte->Entry(
        -width        => 20,
        -textvariable => \$info{$_}
    );
    $texte->windowCreate( 'end', -window => $champ );
    $texte->insert( 'end', "\n" );
}
$texte->configure( -state => 'disabled' );    # Empêche la saisie

MainLoop;

La figure 8.6 montre la version Win32 de cette fenêtre.

Image non disponible
Figure 8.6 : Widget texte contenant d'autres widgets

On désactive le widget texte avant de lancer MainLoop, car on ne veut pas que l'utilisateur entre du texte directement dans le widget texte. Cela ne désactive que la possibilité d'entrer ou de supprimer du texte - les widgets internes fonctionnent quand même normalement. On désactive aussi l'option -wrap pour que les étiquettes et les zones de saisie ne passent pas accidentellement à la ligne lorsque la fenêtre change de taille.

On pourrait également placer un widget texte dans un autre widget texte, mais vous ne le ferez probablement pas.

VIII-Q-1. Les méthodes window

Comme nous l'avons vu avec l'exemple précédent, la méthode windowCreate permet d'insérer un widget imbriqué. Celui-ci doit d'abord avoir été créé et être un fils du widget texte. La syntaxe générale est :

 
Sélectionnez
$widget = $texte->Widget( - ); 
$texte->windowCreate(indice, 
                      -window => $widget [ , option => valeur ] );

Dans l'exemple précédent, nous avons utilisé l'indice 'end', mais n'importe quel indice de widget texte convient pour insérer des widgets imbriqués. La seule option utilisée est -window avec une référence au nouveau widget.

Voici les options des méthodes window :

-align => base

  • Les valeurs possibles de base sont 'baseline', 'bottom', 'center', ou 'top'. Cette option détermine où le widget sera placé dans la ligne s'il est plus petit qu'elle. La valeur par défaut est 'center'.

-padx => montant et -pady => montant

  • Ajoute de l'espace autour du widget dans les directions x et y, respectivement.

-stretch => 0 | 1

  • Une valeur vraie étire le widget pour qu'il remplisse la ligne de haut en bas.

-window => $widget

  • Prend une référence à un autre widget.

Il existe plusieurs formes de méthodes window : la forme Create crée un widget dans le widget texte, et la forme Names nous permet de savoir quels types de widgets sont incorporés dans le widget texte.

 
Sélectionnez
@types = $texte->windowNames();

Le résultat sera quelque chose comme :

 
Sélectionnez
.text.radiobutton.text.label.text.button.text.entry.text.checkbutton

La méthode windowCget permet d'obtenir des informations sur les options utilisées lors de la création du widget dans le widget texte :

 
Sélectionnez
$valeur = $texte->windowCget(indice, option);

Pour utiliser windowCget, il faut connaître l'indice actuellement occupé par le widget (chaque widget occupe la place d'un caractère dans le widget texte, même s'il semble prendre plus de place).

La forme Configure permet de modifier les options associées au widget situé à un indice donné, ou d'obtenir la valeur d'une option de configuration :

 
Sélectionnez
$texte->windowConfigure(indice [, option => valeur ] );

Rappelez-vous que les seules options utilisables avec cette méthode sont -align, -padx, -pady, -stretch et -window. À part ça, windowConfigure se comporte comme n'importe quelle méthode configure classique. Pour modifier directement $widget, on utilise $widget->configure(...).

VIII-R. Test du code

La méthode debug prend un booléen comme paramètre éventuel :

 
Sélectionnez
$texte->debug( [ booléen ] );

Si la valeur fournie est vraie, les tests internes de consistance des données seront activés sur le code de l'arbre binaire associé aux widgets texte. Sinon, les tests ne seront pas assurés. Sans aucun paramètre, la méthode debug renverra la valeur "on" si elle est active, et "off" sinon. Tous les widgets texte d'une même application partagent le même commutateur de test.

VIII-R-1. Recherche

Les méthodes scanMark et scanDragto sont utilisées en interne avec le widget texte. Un appel à scanMark enregistre simplement les valeurs x et y qui lui sont passées pour les utiliser plus tard avec scanDragto. scanMark renvoie une chaîne vide.

 
Sélectionnez
$texte->scanMark(x, y);

scanDragto prend aussi les coordonnées x et y, et les compare à celles fournies à scanMark. La partie visible du widget texte est alors ajustée de dix fois la différence entre les deux paires de coordonnées.

 
Sélectionnez
$texte->scanDragto(x, y);

VIII-S. Essayez et amusez-vous !

  • Créez un widget texte muni d'une barre de défilement. Insérez un bouton dont le texte décrit la couleur de premier plan du widget texte. Lorsque l'on clique sur ce bouton, faites en sorte qu'il passe en revue plusieurs couleurs et qu'il mette à jour l'option -foreground du bouton et du texte. Comme application pratique, on peut envisager d'afficher plusieurs boutons, chacun étant associé à une couleur de l'application. Lorsqu'un bouton est cliqué, on modifie la couleur (éventuellement à l'aide du widget composite ColorEdit).
  • Créez un widget texte affichant un fichier uniquement accessible en lecture. Créez deux boutons, l'un pour diminuer la taille de la fonte du widget texte, l'autre pour l'augmenter.

précédentsommairesuivant
Lorsque vous avez installé le module Tk avec Perl, la démo widget s'est aussi installée. Tapez widget sur la ligne de commande pour voir les possibilités des widgets en Perl/Tk.
Les lecteurs les plus attentifs auront remarqué que cette capture d'écran a un aspect légèrement différent de celles déjà vues. C'est dû au fait qu'elle a été faite sous Windows 95 au lieu de X Window. Remarquez le « Tk » dans le coin supérieur gauche, et les contrôles de la fenêtre dans le coin supérieur droit.

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.