Introduction à Perl/Tk

Interfaces graphiques avec Perl


précédentsommairesuivant

IX. Le widget canevas

Le widget canevas sert principalement à dessiner des éléments comme des arcs, des lignes, des rectangles, des cercles, etc. Il peut aussi contenir du texte et d'autres widgets. On peut l'assimiler à une sorte de toile : elle est blanche jusqu'à ce que vous décidiez d'y dessiner quelque chose, mais, à la différence de celle-ci, qui a une taille fixe, un canevas peut être parcouru dans les deux directions. Voici quelques exemples d'utilisations possibles de ce widget :

  • création d'un programme de dessin ;
  • affichage d'un graphique en fonction de valeurs entrées par l'utilisateur ;
  • création d'un ascenseur personnalisé.

Tout élément créé dans un canevas peut posséder des liaisons lui permettant d'interagir facilement avec l'utilisateur.

IX-A. Création d'un canevas

Je vous conseille de toujours créer un canevas grâce à la méthode Scrolled, sauf si vous êtes absolument certain qu'il sera d'une taille fixe convenant à la fenêtre :

 
Sélectionnez
$canevas = $mw->Canvas( [ option => valeur, ... ] )->pack(); 
# ou... 
$canevas = $mw->Scrolled('Canvas', [ option => valeur, ... ] )->pack();

La première ligne crée un canevas simple, tandis que la deuxième munit le sien de barres de défilement (voir le chapitre 6, Barres de défilement, pour plus d'informations sur tout ce que l'on peut faire avec la méthode Scrolled). Pour créer un widget canevas, on utilise le widget parent pour invoquer la méthode Canvas et lui passer toutes les valeurs des options nécessaires. Cette méthode renvoie une référence au canevas ainsi créé.

Avant de passer en revue les options et les méthodes disponibles pour un canevas, voici quelques informations qu'il est bon de connaître lorsque l'on utilise ce type de widget.

IX-B. Système de coordonnées

Un widget canevas utilise un système de coordonnées particulier afin de décrire les emplacements des éléments qu'il contient. Ce système ressemble assez à un système de coordonnées « renversé ».

La figure 9.1 illustre cela.

Image non disponible
Figure 9.1 : Système de coordonnées d'un canevas

Les coordonnées x ne présentent rien de particulier : elles augmentent de gauche à droite. Les coordonnées y semblent avoir bu de la Vodka : les valeurs les plus hautes sont vers le bas plutôt qu'au sommet, car le point 0; 0 est dans le coin supérieur gauche. Bien que cela soit rare, on peut utiliser des coordonnées négatives dans un canevas.

Ce système de coordonnées n'est pas difficile à gérer dès que l'on a compris ce qui se passe, mais si l'on tente de dessiner un bâtiment en ayant à l'esprit un système de coordonnées standard (avec y augmentant du bas vers le haut), il reposera sur le toit.

Il y a plusieurs façons de gérer tout cela. La première consiste à ajuster sa façon de penser afin de toujours considérer que les coordonnées y sont plus grandes vers le bas (et oublier toutes ces années durant lesquelles on a lutté pendant les cours de géométrie). Si vous êtes aussi têtu que moi, vous pouvez continuer à penser en coordonnées normales et faire en sorte que votre programme effectue quelques calculs avant d'envoyer les coordonnées y aux fonctions du canevas (multiplier toutes les coordonnées y par - 1 est astucieux, non ?).

Quelle que soit la méthode retenue, soyez cohérent et commentez bien votre code.

Les coordonnées x et y peuvent être indiquées dans n'importe quelle unité d'écran ; par défaut, il s'agira de pixels. Si l'on place un m après une coordonnée, la distance sera mesurée en millimètres. Les autres lettres utilisables sont p pour les points d'imprimante, i pour les pouces (inches), et c pour les centimètres. Nous utiliserons l'unité par défaut, le pixel, pour tous les exemples de ce chapitre.

IX-C. La région de parcours

La région de parcours (scrollable region) est la portion du widget canevas que l'utilisateur peut voir. Si l'on ne crée pas une telle zone (en utilisant l'option -scrollregion), l'utilisateur pourra faire défiler le canevas indéfiniment dans les deux directions et les barres de défilement ne refléteront pas les emplacements des éléments contenus dans le widget.

La figure 9.2 montre un exemple de région de parcours comparée à la surface visible d'un canevas. Si ces deux surfaces avaient la même taille, nous n'aurions pas besoin de barres de défilement pour le canevas (si l'on en utilisait, leurs ascenseurs rempliraient complètement la zone de défilement).

Image non disponible
Figure 9.2 : Région de parcours comparée à la zone visible

Les flèches sur les axes de la figure 9.2 indiquent que le canevas peut être encore plus grand que la région de parcours indiquée. Si vous décidez, par exemple, d'ajouter un cercle en dehors de celle-ci, vous devrez ajuster cette région pour que l'utilisateur puisse voir ce nouveau cercle.

La meilleure façon de faire cela est d'utiliser la méthode bbox qui renvoie une boîte de dimensionnement pour tous les éléments correspondant aux marqueurs que vous lui indiquez. Voici à quoi ressemblerait le code :

 
Sélectionnez
$canevas->configure(-scrollregion => [ $canevas->bbox("all") ]);

L'exécution de cette instruction, après avoir ajouté ou supprimé des éléments au canevas, réinitialise la région de parcours à la taille nécessaire. Bien sûr, si l'on ajoute d'un seul coup de nombreux éléments, il faudra attendre de les avoir tous ajoutés avant de mettre à jour la région de parcours.

IX-D. Utilisation de bind avec un canevas

Lorsque l'on tente d'utiliser la méthode bind avec un widget canevas, on se trouve confronté à des problèmes inattendus. Soit l'on obtient une erreur et notre script ne fonctionne pas, soit le script fonctionne, mais la liaison semble n'avoir aucun effet. Afin d'éviter cela, il faut écrire explicitement Tk::bind au lieu de bind (car un canevas dispose de sa propre méthode bind qu'il faut éviter d'utiliser) :

 
Sélectionnez
$canevas = $mw->Canvas(); 
$canevas->Tk::bind("<Button-1>", sub { print "liaison !\n"; });

Vous pouvez aussi utiliser la notation SUPER::bind au lieu de Tk::bind : les deux sont correctes(25).

Si vous avez utilisé la méthode Scrolled pour créer votre canevas, vous rencontrerez une difficulté supplémentaire : il faudra utiliser la méthode Subwidget pour obtenir le widget canevas :

 
Sélectionnez
$canevas = $mw->Scrolled("Canvas"); 
$canevas_reel = $canevas->Subwidget("canvas"); 
$canevas_reel->Tk::bind("<Button-1>", sub { print "liaison !\n" });

À part ces petits désagréments, bind fonctionne comme on est en droit de s'y attendre. Voici un petit exemple (assez utile), qui affiche les coordonnées de l'endroit sur lequel on a cliqué :

 
Sélectionnez
$c = $mw->Scrolled("Canvas")->pack(); 
$canevas = $c->Subwidget("canvas"); 
$canevas->Tk::bind("<Button-1>", [ \&affiche_xy, Ev('x'), Ev('y') ]); 
sub affiche_xy { 
    my ($canev, $x, $y) = @_; 
    print "(x,y) = ", $canev->canvasx($x), ", ", 
    $canev->canvasy($y), "\n"; 
}

IX-E. Options d'un canevas

Les options énumérées dans cette section affectent le widget entier, ainsi que les éléments qu'il contient. Ceux-ci sont des cercles, des lignes, des rectangles, du texte, ou d'autres widgets. Ces options agissent comme prévu (voir le chapitre 3, Le bouton de base, pour l'essentiel des options, et le chapitre 6 pour celles spécifiques aux barres de défilement) : -background, -borderwidth, -cursor, -height, -highlightbackground, -highlightcolor, -highlightthickness, -relief, -takefocus, -width, -xscrollcommand, et -yscrollcommand.

IX-E-1. Nouvelles options

Lorsque l'on sélectionne des éléments du canevas avec la souris, celui-ci détermine si le curseur est ou non à l'intérieur de l'élément. L'option -closeenough contrôle la proximité que doit avoir la souris avec l'élément avant qu'elle soit considérée comme étant à l'intérieur de celui-ci. La valeur par défaut de -closeenough est « 1.0 », qui indique une proximité de un pixel. Cette option accepte n'importe quel nombre réel (qui sera toujours considéré en pixels).

Nous avons rapidement traité de l'option -scrollregion dans la section sur « La région de parcours », plus haut dans ce chapitre. Cette option prend une référence à une liste de quatre coordonnées qui décrivent une boîte de dimensionnement de la région de parcours du canevas et sont exprimées dans l'ordre [ minx, miny, maxx, maxy ]. On peut aussi considérer que ces coordonnées définissent, respectivement, les bords gauche, haut, droit et bas de celle-ci.

Normalement, le widget canevas limite l'utilisateur à ne voir que la région définie par l'option -scrollregion. On peut abolir cette limite en utilisant -confine => 0. La valeur par défaut de -confine est 1.

IX-E-2. Nouvelles options de défilement

Les options -xscrollcommand et -yscrollcommand fonctionnent toutes les deux comme on l'a expliqué au chapitre 6, mais deux options supplémentaires agissent sur la façon dont le canevas fait défiler son contenu : -xscrollincrement et -yscrollincrement. Chacune d'elles prend pour valeur une distance d'écran qui sera l'unité utilisée par le canevas pour défiler dans la direction concernée. Avec -xscrollincrement => 10, par exemple, le contenu du canevas sera décalé, à chaque clic sur une flèche de la barre de défilement horizontale, d'une valeur multiple de 10. Pour résumer, le canevas décalera son contenu de 10 pixels dans la direction de la flèche.

Si la valeur associée à -xscrollincrement ou -yscrollincrement est inférieure ou égale à 0, le défilement utilise les pas de progression normaux.

IX-E-3. Options pour le texte

Les options suivantes s'appliquent à tout le widget canevas, bien qu'elles n'affectent réellement que les éléments de texte du canevas : -insertbackground,-insertborderwidth, -insertofftime,-insertontime, -insertwidth, -selectbackground,-selectborderwidth, et -selectforeground. Ces options fonctionnent comme pour les zones de saisie et les widgets texte ; elles sont décrites en détail aux chapitres 5, Les widgets étiquette et de saisie, et 6, Barres de défilement.

IX-E-4. Liste des options du widget canevas

Toutes les options suivantes sont utilisables avec la méthode Canvas :

-background => couleur

  • Configure la couleur de fond du canevas.

-borderwidth => montant

  • Modifie la largeur des bords du canevas.

-closeenough => montant

  • Configure la distance à partir de laquelle on considère que le curseur est à l'intérieur d'un élément. montant est un nombre réel.

-confine => 1 | 0

  • Si elle vaut 1 (valeur par défaut), cette option précise que le canevas se limitera lui-même à la région définie par -scrollregion.

-cursor => nom_curseur

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

-height => montant

  • Configure la hauteur du canevas.

-highlightbackground => couleur

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

-highlightcolor => couleur

  • Configure la couleur qu'aura le rectangle de focus lorsque le canevas a le focus clavier.

-highlightthickness => montant

  • Fixe l'épaisseur du rectangle de focus. Le montant par défaut est 2.

-insertbackground => couleur

  • Configure la couleur de la zone située derrière le point d'insertion.

-insertborderwidth => montant

  • Fixe la largeur des bords du point d'insertion.

-insertofftime => millisecondes

  • Configure le délai pendant lequel le point d'insertion disparaît de l'écran lorsqu'il clignote.

-insertontime => millisecondes

  • Configure le délai pendant lequel le point d'insertion apparaît à l'écran lorsqu'il clignote.

-insertwidth => montant

  • Fixe la largeur du point d'insertion.

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

  • Précise l'aspect du contour du canevas. Le contour par défaut est 'flat'.

-scrollregion => [ gauche, haut, droit, bas ]

  • Définit la zone que l'utilisateur pourra faire défiler.

-selectbackground => couleur

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

-selectborderwidth => montant

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

-selectforeground => couleur

  • Configure la couleur du texte sélectionné.

-takefocus => 0 | 1 | undef

  • Détermine si le canevas pourra obtenir le focus clavier. La valeur par défaut laisse l'application décider.

-width => montant

  • Fixe la largeur du canevas.

-xscrollcommand => fct_rappel

  • Indique la fonction de rappel à utiliser lorsque le canevas est parcouru horizontalement (lorsque la méthode Scrolled est utilisée, cette option est automatiquement initialisée avec la fonction de rappel correcte).

-xscrollincrement => montant

  • Fixe la distance de déplacement du contenu du canevas lorsque l'utilisateur emploiera la flèche de la barre de défilement horizontale.

-yscrollcommand => fct_rappel

  • Indique la fonction de rappel à utiliser lorsque le canevas est parcouru verticalement.

-yscrollincrement => montant

  • Fixe la distance par laquelle le contenu du canevas se déplacera lorsque l'utilisateur emploiera la flèche de la barre de défilement verticale.

IX-F. Création d'éléments dans un canevas

Le but premier d'un canevas est de contenir des éléments : on peut y créer des arcs, des bitmaps, des images, des lignes, des rectangles, des ovales (cercles), des polygones, du texte et des widgets. Chacun de ces éléments dispose d'une méthode de création createXXX, où XXX est le type de l'élément concerné. Toutes ces méthodes de création renvoient un identificateur unique, pouvant servir à désigner l'élément. Lorsqu'une méthode prend un marqueur ou un identificateur comme paramètre, l'identificateur est celui renvoyé par la méthode de création.

IX-F-1. Arcs

Pour créer un arc, il faut préciser un rectangle de dimensionnement à l'aide de deux paires de coordonnées x et y. L'arc est tracé dans les limites de ce rectangle. Des options supplémentaires permettent de modifier la façon dont celui-ci est tracé dans le canevas ; nous les décrirons brièvement. L'instruction createArc de base est la suivante :

 
Sélectionnez
$id = $canevas->createArc(x1,y1, x2,y2);

Les options supplémentaires sont précisées après les coordonnées :

 
Sélectionnez
$id = $canevas->createArc(x1,y1, x2,y2, option => valeur);

Chaque option d'un arc peut être utilisée plus tard par les méthodes itemcget et itemconfigure. Celles-ci sont :

-extent => degrés

  • La longueur de l'arc est précisée en degrés à l'aide de cette option. Cette longueur vaut 90 degrés par défaut. L'arc est tracé dans le rectangle défini par (x1, y1) et (x2, y2), de son point de départ (voir l'option -start) et en sens inverse des aiguilles d'une montre. degrés doit être un nombre compris entre -360 et 360 ; sinon, la valeur utilisée sera celle indiquée modulo 360.
    Voici des exemples d'utilisation de l'option -extent :
 
Sélectionnez
# Trace la moitié d'un ovale 
$canevas->createArc(0,0, 100,150, -extent => 180); 
# Trace les 3/4 d'un ovale 
$canevas->createArc(0,0, 100,150, -extent => 270);

-fill => couleur

  • Remplit l'arc avec couleur. Par défaut, un arc n'a pas de couleur de remplissage.

-outline => couleur

  • Normalement, un arc est tracé avec un contour noir. Pour modifier cette couleur par défaut, on utilisera cette option. La couleur du contour est distincte de celle du remplissage ; pour avoir un objet uniforme, il suffit de choisir la même teinte pour -fill et -outline.

-outlinestipple => bitmap

  • Pour utiliser cette option, il faut aussi définir -outline. Normalement, le contour d'un arc est tracé avec un trait plein ; on utilisera -outlinestipple pour utiliser un motif en bitmap afin de tracer le contour.

-start => degrés

  • La valeur associée à cette option détermine l'endroit où Perl/Tk débutera le tracé de l'arc. La position de départ par défaut est à trois heures(26) et les degrés indiqués ici sont ajoutés à cette position, mais dans l'ordre inverse des aiguilles d'une montre. On utilisera -start => 90 pour démarrer le tracé de l'arc à douze heures, -start => 180 pour le démarrer à neuf heures, etc.

-stipple => bitmap

  • Cette option permet de remplir l'arc avec un motif en bitmap, mais uniquement si l'option -fill a aussi été utilisée.

-style => 'pieslice' | 'chord' | 'arc'

  • Le -style d'un arc détermine la façon dont il sera tracé. La valeur par défaut, "pieslice" (NDT Littéralement, "part de gâteau" en français), trace l'arc et deux lignes partant du centre de celui-ci et se terminant aux extrémités du segment. La valeur "chord" trace l'arc et une ligne reliant les deux extrémités de son segment. La valeur "arc" ne trace que l'arc, sans ligne. Les options -fill et -stipple sont ignorées si cette dernière valeur est utilisée.

-tags => liste_marqueurs

  • Cette option permet d'assigner des marqueurs à un arc au moment de sa création. La valeur associée à -tags est une liste anonyme de marqueurs ; par exemple :
 
Sélectionnez
$canevas->createArc(0,0, 10,140,-tags => ["arc", "grand"]);
  • Si l'on n'indique qu'un seul marqueur, une liste n'est pas nécessaire :
 
Sélectionnez
$canevas->createArc(0,0, 10,140,-tags => "arc");

-width => montant

  • Précise la largeur du contour. La valeur par défaut est 1.

IX-F-2. Bitmaps

Un widget canevas peut afficher un bitmap à la place du texte, tout comme les boutons et les étiquettes. On utilise createBitmap pour insérer un bitmap :

 
Sélectionnez
$id = $canevas->createBitmap(x,y);

Il faut, bien sûr, utiliser l'option -bitmap pour préciser le bitmap à afficher ou vous ne verrez rien. On crée donc vraiment un bitmap ainsi :

 
Sélectionnez
$id = $canevas->createBitmap(x,y, -bitmap => bitmap);

J'ignore la raison pour laquelle le bitmap n'est pas simplement le troisième paramètre : c'est comme ça. Les autres options de createBitmap sont :

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

  • L'option -anchor précise comment sera placé le bitmap dans le canevas, relativement aux coordonnées x et y indiquées. La valeur par défaut est "center", qui place le centre de l'image à ces coordonnées. L'utilisation d'un point cardinal unique ("e", par exemple) placerait le centre de ce bord aux coordonnées x et y.

-background => couleur

  • Cette option précise la couleur à utiliser pour tous les pixels à 0 (zéro) du bitmap. Si l'on ne précise pas cette option, ou si sa valeur est une chaîne vide, les pixels à 0 seront transparents. Ce sont ces pixels qui forment le fond d'un bitmap.

-bitmap => nom_bitmap

  • Il faut utiliser cette option pour indiquer au canevas quel bitmap afficher. On peut utiliser les bitmaps internes, comme 'info' ou 'warning', comme pour le widget bouton, ou indiquer un nom de fichier. N'oubliez pas qu'il faut mettre un signe @ devant le nom du fichier bitmap.

-foreground => couleur

  • La couleur du premier plan d'un bitmap est l'opposée de celle de son fond (par définition, les bitmaps n'ont que deux couleurs). Cette option colorie tous les pixels à 1 en couleur. La valeur par défaut est noir.

-tags => liste_marqueurs

  • Cette option assigne des marqueurs à un bitmap lors de sa création. La valeur associée à -tags est une liste anonyme de marqueurs ; par exemple :
 
Sélectionnez
$canevas->createBitmap(0,0, -bitmap => 'info', -tags => ["info", "bitmap"]);
  • Si vous n'indiquez qu'un seul marqueur, une liste n'est pas nécessaire :
 
Sélectionnez
$canevas->createBitmap(0,0, -bitmap => 'info', -tags => "bitmap");

IX-F-3. Images

S'il est possible de créer un bitmap dans un canevas, il est normal que l'on puisse aussi créer une image. Pour ce faire, on utilise la méthode createImage :

 
Sélectionnez
$id = $canevas->createImage(x,y, -image => nom_image);

Ici encore, vous devez indiquer l'image à afficher ou vous ne verrez rien. Les autres options de createImage sont :

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

  • Cette option fonctionne avec une image exactement comme avec un bitmap. Elle précise la façon dont sera positionnée l'image par rapport aux coordonnées x et y. Sa valeur par défaut est "center".

-image => nom_image

  • L'option -image indique quelle image afficher. Sa valeur est, en fait, une référence à une image créée par la méthode Photo ou Bitmap (le chapitre 3 donne plus d'informations sur la façon d'indiquer un fichier image).

-tags => liste_marqueurs

  • On utilise cette option pour assigner des marqueurs à une image. La valeur associée à -tags est une liste anonyme ; par exemple :
 
Sélectionnez
$canevas->createImage(0,0, -image => $ptr_image, 
                           -tags => ["image", "bleu"]);
  • Une liste est inutile si l'on ne donne qu'un seul marqueur :
 
Sélectionnez
$canevas->createImage(0,0, -image => $ptr_image, 
                           -tags => "image");

IX-F-4. Lignes

La méthode createLine permet, en réalité, de créer plusieurs lignes reliées entre elles, pas seulement une ligne unique. Les deux premières paires de coordonnées que vous indiquez créent la première ligne, et toute paire supplémentaire continuera la ligne (brisée) jusqu'à ce point.

 
Sélectionnez
$id = $canevas->createLine(0,0, 400,400); # Crée une seule ligne 
$id = $canevas->createLine(0,0, 400,400, -50,240); # deux lignes

On peut utiliser des options à la suite des coordonnées afin de configurer la ou les lignes ; ces options et leurs valeurs possibles sont les suivantes :

-arrow => "none" | "first" | "last" | "both"

  • Cette option permet de placer des flèches aux extrémités de la ligne. Si la méthode createLine crée plusieurs lignes, seuls le premier et/ou le dernier point peuvent devenir des flèches. Pour que chaque ligne soit traitée, il faut utiliser plusieurs instructions createLine.

-arrowshape => [ dist1, dist2, dist3 ]

  • L'option -arrowshape ne s'applique que si -arrow est également utilisée. La figure 9.3 montre la signification des trois distances.
Image non disponible
Figure 9.3 : Forme d'une flèche

On indique les trois distances à l'aide d'une liste anonyme comme dans l'exemple qui suit :

 
Sélectionnez
$canevas->createLine(
    10, 10, 200, -40,
    -arrow      => "both",
    -arrowshape => [ 20, 20, 20 ]
);

-capstyle => "butt" | "projecting" | "round"

  • Cette option permet de spécifier autre chose que des flèches pour les extrémités d'une ligne.

-fill => couleur

  • L'option -fill porte mal son nom, car elle ne remplit rien ; la ligne est simplement tracée d'une autre couleur que le noir par défaut.

-joinstyle => "bevel" | "miter" | "round"

  • Cette option précise comment plusieurs lignes seront jointes. La valeur par défaut est "miter". Si l'on ne crée qu'une seule ligne, -joinstyle est sans effet.

-smooth => 1 | 0

  • Si cette option vaut 1, la ligne sera tracée comme une courbe de Bézier. Les deux premières lignes formeront la première spline, les deux suivantes, la seconde spline, etc. Pour créer une ligne droite, il suffit de répéter les points terminaux de la ligne droite désirée (ou de réutiliser createLine pour créer une autre ligne).

-splinesteps => nombre

  • Lorsque l'on utilise -smooth, plus -splinesteps est élevée, plus la courbe sera douce. Pour connaître le nombre d'étapes nécessaires à l'obtention de l'effet voulu, il faut essayer plusieurs valeurs.

-stipple => bitmap

  • Cette option permet de tracer la ligne en utilisant un motif bitmap (les 1 seront colorés, les 0 seront transparents). bitmap peut être un nom de bitmap intégré ou un nom de fichier. Plus la ligne est large (cf. l'option -width), plus le motif ressortira.

-tags => liste_marqueurs

  • Permet d'affecter des marqueurs à une ou plusieurs lignes au moment de leur création. La valeur associée à -tags est une liste anonyme ; par exemple :
 
Sélectionnez
$canevas->createLine(0,0, 100,100, -tags => ["ligne", "bleu"]);
  • Si l'on n'indique qu'un seul marqueur, une liste n'est pas nécessaire :
 
Sélectionnez
$canevas->createLine(0,0, 100,100, -tags => "ligne");

-width => montant

  • On peut élargir la ligne à l'aide de cette option. Normalement, une ligne ne fait qu'un pixel de large. montant est exprimable dans n'importe quelle distance d'écran (centimètres, pouces, etc.).

IX-F-5. Ovales

S'il est tracé correctement, un ovale est un cercle. Pour créer un cercle/ovale, on utilise la méthode createOval et l'on indique deux paires de coordonnées définissant un rectangle (ou un carré) dans lequel sera tracé le cercle/ovale. Voici un bref exemple :

 
Sélectionnez
$id = $canevas->createOval(0,0, 50,50); # Crée un cercle 
$id = $canevas->createOval(0,0, 50,100); # Crée un ovale

Les options d'un ovale sont classiques, je me contenterai donc de brèves descriptions :

-fill => couleur

  • L'ovale sera rempli avec la couleur indiquée. Cette couleur est différente de celle du contour. Par défaut, un ovale n'est pas coloré.

-outline => couleur

  • Le contour est la ligne délimitant le cercle. Par défaut, sa couleur est noire, mais on peut la modifier à l'aide de cette option. Si vous utilisez la même couleur pour le contour et pour le remplissage, l'ovale apparaîtra comme une surface pleine.

-stipple => bitmap

  • Cette option permet de remplir l'ovale avec un motif bitmap (les bits à 1 seront colorés, les bits à 0 seront transparents) : elle est sans effet si l'option -fill n'est pas aussi utilisée. bitmap peut être un bitmap intégré ou un nom de fichier.

-tags => liste_marqueurs

  • Permet d'affecter des marqueurs à un ovale au moment de sa création. La valeur associée à -tags est une liste anonyme ; par exemple :
 
Sélectionnez
$canevas->createOval(0,0, 100,100, -tags => ["ovale", "bleu"]);
  • Si l'on n'indique qu'un seul marqueur, une liste n'est pas nécessaire :
 
Sélectionnez
$canevas->createOval(0,0, 100,100, -tags => "ovale");

-width => montant

  • On peut élargir la ligne de contour d'un ovale à l'aide de cette option. Normalement, ce contour n'occupe qu'un pixel de large.

IX-F-6. Polygones

Un polygone est ni plus ni moins un ensemble de lignes avec le premier point automatiquement relié au dernier pour former une figure fermée. La méthode createPolygon nécessite au moins trois paires de coordonnées x, y. Le code suivant, par exemple, crée un triangle :

 
Sélectionnez
$id = $canevas->createPolygon(1000,1000, 850,950, 30,40);

On peut ajouter des paires x, y supplémentaires :

 
Sélectionnez
$id = $canevas->createPolygon(1000,1000, 850,950, 30,40, 500,500);

Les options de createPolygon sont les mêmes que celles de createLine : -fill, -outline, -smooth, -splinesteps, -stipple, -tags, et -width. N'oubliez pas que createPolygon relie le premier point au dernier afin de fermer la figure.

IX-F-7. Rectangles

Comme si createLine ou createPolygon ne suffisaient pas pour créer un rectangle, la méthode createRectangle existe aussi. Celle-ci ne prend que deux paires de coordonnées, représentant les coins opposés de la surface rectangulaire :

 
Sélectionnez
$id = $canevas->createRectangle(10,10, 50,150);

Ici encore, les options possibles, -fill, -outline, -stipple, -tags, et -width, ont déjà été vues avec les autres méthodes de création. Voici néanmoins quelques exemples :

 
Sélectionnez
# Un rectangle bleu avec un contour noir : 
$canevas->createRectangle(10,10, 50,150, -fill => 'blue'); 
# Un rectangle bleu avec un contour plus épais : 
$canevas->createRectangle(10,10, 50,150, -fill => 'blue', -width => 10);

IX-F-8. Textes

Enfin ! Un type d'élément ne contenant pas de tracé ! On peut ajouter du texte dans un widget canevas à l'aide de la méthode createText. Celle-ci nécessite une paire de coordonnées x, y qui indique où placer le texte dans le canevas, ainsi que le texte à afficher :

 
Sélectionnez
$id = $canevas->createText(0,0, -text => "origine");

En fait, l'option -text est facultative, mais, si vous ne l'utilisez pas, vous ne verrez rien à l'écran. Comme cela n'a aucun intérêt, nous supposerons que vous préciserez toujours cette option avec le texte à afficher. Les autres options de createText sont :

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

  • Cette option détermine l'emplacement du texte par rapport aux coordonnées x et y. Le comportement par défaut consiste à centrer le texte sur ce point, quelle que soit la taille du texte.

-fill => couleur

  • Normalement, le texte est écrit en noir ; on peut modifier cela à l'aide de cette option qui porte mal son nom lorsqu'il s'agit de texte (habituellement, les widgets utilisent -foreground pour modifier la couleur du texte). Avec l'option -fill => 'blue', par exemple, le texte apparaîtra en bleu.

-font => nom_fonte

  • Modifie la fonte utilisée pour afficher le texte.

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

  • Si le texte affiché comporte plusieurs lignes, cette option permet de contrôler son alignement. Par défaut, le texte sera aligné à gauche.

-stipple => bitmap

  • Cette option est un peu bizarre, mais elle existe bien… Si l'on indique un nom de bitmap (ou de fichier), le texte sera écrit en utilisant le motif du bitmap. Cela rendra souvent le texte illisible donc ne l'utilisez pas, sauf avec de grandes fontes.

-tags => liste_marqueurs

  • liste_marqueurs est une liste anonyme de marqueurs ou un simple marqueur, qui seront affectés au texte.

-text => chaîne

  • Cette option est nécessaire ; la chaîne indiquée est affichée dans le canevas, aux coordonnées x et y.

-width => montant

  • Il s'agit encore d'une option mal nommée, car elle ne modifie pas la largeur des caractères du texte, mais détermine la longueur maximale d'une ligne de texte. Si le texte dépasse cette limite, la ligne sera automatiquement coupée pour former une seconde ligne. Par défaut, montant vaut 0, ce qui ne coupera les lignes qu'en présence d'un caractère de fin de ligne. Les lignes sont toujours coupées sur des espaces, donc aucun mot ne sera coupé en son milieu.

IX-F-9. Indices des éléments texte

Les méthodes concernant les éléments texte demandent parfois une valeur d'indice. Les indices des widgets texte ont été traités au chapitre 8 et les indices d'un élément texte d'un canevas leur ressemblent. Chaque élément est toutefois considéré ici comme une ligne unique (même si elle contient des caractères \n). Les valeurs d'indices possibles sont les suivantes :

n

  • n est une valeur numérique : 0 ou 12, par exemple. Le premier caractère a l'indice 0, le second a l'indice 1, etc.

"end"

  • Désigne l'emplacement placé immédiatement après le dernier caractère. Cet indice est souvent utilisé avec la méthode insert pour ajouter du texte à la fin d'une chaîne.

"insert"

  • Désigne le caractère placé immédiatement avant le point d'insertion.

"sel.first"

  • Le premier caractère du texte sélectionné. Ne peut être utilisé que si une sélection est active.

"sel.last"

  • Le dernier caractère du texte sélectionné. Ne peut être utilisé que si une sélection est active.

"@x, y"

  • Désigne le caractère le plus près du point de coordonnées x, y du canevas (ce ne sont pas des coordonnées écran).

IX-F-10. Suppression de caractères

La méthode dchars permet de supprimer des caractères d'un élément texte :

 
Sélectionnez
$canevas->dchars(marqueur/id, premier [, dernier ] )

On indique un marqueur ou un identificateur pour désigner le ou les éléments de texte, et l'indice où commencer la suppression. Si dernier n'est pas utilisé, seul le caractère situé à l'indice premier sera supprimé. Le reste de la chaîne ne sera pas affecté.

IX-F-11. Positionnement du point d'insertion

On peut placer explicitement le point d'insertion à l'aide de la méthode icursor :

 
Sélectionnez
$canevas->icursor(marqueur/id, indice)

Le curseur n'apparaîtra que si l'élément concerné a le focus clavier, mais on peut quand même configurer la position du point s'il ne l'a pas.

IX-F-12. Informations sur les indices

On peut retrouver un indice en fonction d'un autre, à l'aide de la méthode index. Voici un exemple qui clarifiera son utilisation :

 
Sélectionnez
$indice = $canevas->index("element", "sel.first");

Cette instruction renverra l'indice numérique associé au premier caractère sélectionné de l'élément texte. Si plus d'un élément correspond au marqueur ou à l'identificateur indiqué (ici, il s'agit d'un marqueur nommé "element"), le premier rencontré sera utilisé.

IX-F-13. Ajout de texte

La méthode insert permet d'ajouter du texte à un élément texte :

 
Sélectionnez
$canevas->insert(marqueur/id, indice, chaîne)

IX-F-14. Sélection de texte

La méthode selectClear annule la sélection (toute sélection, en fait, car cette méthode n'utilise ni marqueur ni identificateur) :

 
Sélectionnez
$canevas->selectClear();

Les méthodes selectFrom et selectTo, quant à elles, permettent de sélectionner une portion de texte. Les deux lignes suivantes sélectionnent le texte du début à la fin du premier élément correspondant au marqueur « marqueur_texte » :

 
Sélectionnez
$canevas->selectFrom("marqueur_texte", 0); 
$canevas->selectTo("marqueur_texte", "end");

La méthode selectAdjust permet d'ajuster la sélection :

 
Sélectionnez
$canevas->selectAdjust(marqueur/id, indice)

Pour obtenir l'identificateur de l'élément sélectionné, on utilisera la méthode selectItem :

 
Sélectionnez
$id = $canevas->selectItem()

IX-F-15. Widgets

Un canevas peut contenir n'importe quel type de widget : bouton, case à cocher, widget texte, ou même un autre canevas (au cas où vous seriez un peu fou).

Pour cela, on utilise la méthode createWindow, qui nécessite que le widget à placer dans le canevas soit d'abord créé. Voici un exemple :

 
Sélectionnez
$bouton = $canevas->Button(
    -text    => "Bouton",
    -command => sub {
        print "Un bouton dans le canevas\n";
    }
);
$id = $canevas->createWindow( 0, 0, -window => $bouton );

Certains points méritent d'être notés dans cet exemple (qui est assez classique, si ce n'est la fonction inutile associée au bouton) :

  • le bouton est un fils du widget canevas. Il pourrait descendre d'un ancêtre de celui-ci (être un fils de la fenêtre principale si celle-ci est le parent du canevas). Cependant, il ne doit pas être le fils d'un autre widget de premier niveau n'ayant aucun rapport avec le canevas ;
  • en réalité, la méthode createWindow ne crée pas le widget : elle ne fait que le placer dans le canevas. Le bouton y est positionné aux coordonnées indiquées et ne doit pas être placé à l'écran avec les méthodes pack, grid, ou place ;
  • vous devez créer le widget avant d'appeler createWindow ;
  • si l'on clique sur le bouton, cela invoquera la fonction de rappel qui lui est associée, comme avec tout bouton ;
  • lorsque l'on crée le widget, on peut utiliser n'importe laquelle de ses options pour le configurer. On peut aussi utiliser sa référence ($bouton, par exemple), pour le configurer plus tard.
    Les options suivantes de createWindow ressemblent plus à celles utilisées avec pack
    qu'à des options de widget :

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

  • Le widget sera placé aux coordonnées x, y selon la valeur d'ancrage indiquée par cette option. Par défaut, celle-ci vaut "center", ce qui signifie que le centre du widget sera placé en x, y.

-height => montant

  • Fixe la taille du widget. Sans cette option, celui-ci gardera la taille qu'il avait au moment de sa création (habituellement, il s'agit de la taille naturelle du widget).

-tags => liste_marqueurs

  • liste_marqueurs associe un ou plusieurs marqueurs au widget. Il peut s'agir d'un nom unique, ou d'une liste anonyme de marqueurs.

-width => montant

  • Fixe la largeur du widget. Sans elle, celui-ci conservera la largeur obtenue au moment de sa création (la taille naturelle du widget).

-window => $widget

  • Cette option est obligatoire : sans elle, aucun widget ne sera placé dans le canevas. $widget est une référence à un élément widget que l'on peut avoir créé au préalable, ou au moment de l'appel à createWindow, comme dans l'exemple ci-dessous :
 
Sélectionnez
$canevas->createWindow(
    0, 0,
    -window => $canevas->Button(
        -text => "Bouton",
    )
);

La création du widget au moment de l'appel à createWindow n'a de sens que si l'on n'a pas l'intention d'y faire référence par la suite.

IX-G. Configuration du widget canevas

Comme d'habitude, les méthodes configure et cget, détaillées à l'annexe A, Configuration des widgets avec configure et cget, permettent de configurer ou d'obtenir des informations sur le widget canevas. N'oubliez pas que ces deux méthodes agissent sur le canevas entier (et qu'elles sont donc susceptibles d'affecter les éléments qu'il contient).

IX-H. Configuration des éléments d'un canevas

Pour modifier les options de configuration de n'importe quel élément d'un canevas, il suffit de connaître le nom du marqueur ou l'identificateur de cet élément ; on peut alors utiliser les méthodes itemcget et itemconfigure. Celles-ci se comportent comme cget et configure, mais attendent le marqueur ou l'identificateur du ou des éléments comme premier paramètre. J'ai écrit « du ou des éléments », car un même marqueur peut désigner plusieurs éléments. Voici deux exemples d'utilisation de ces méthodes :

 
Sélectionnez
$couleur = $canevas->itemcget("cercle", -fill); 
$canevas->itemconfigure($ident, -fill => "yellow", -outline => 5);

On doit s'assurer que les options utilisées avec itemconfigure et itemcget sont correctes. Chaque type d'élément reconnaît un certain ensemble d'options ; celles-ci ont été décrites plus haut dans ce chapitre, avec les méthodes de création.

Lorsque l'on configure l'option -tags, la méthode itemconfigure remplacera tous les marqueurs affectés à l'élément. La liste de marqueurs associée à cette option peut aussi être vide, ce qui a pour effet de supprimer tous les marqueurs.

IX-I. Marqueurs

Un ou plusieurs marqueurs peuvent être associés à chaque élément. Nous avons déjà traité de leur utilisation dans l'exposé consacré au widget texte, mais rappelons que des parties de texte peuvent y être désignées par un marqueur. L'association se fait au moment de la création de l'élément, ou après celle-ci, à l'aide de la méthode addtag.

Les deux marqueurs spéciaux, "current" et "all", sont automatiquement assignés et gérés. "all" désigne tous les éléments du canevas, tandis que "current" fait référence à l'élément situé au-dessus des autres et sur lequel pointe la souris. Si ce pointeur se trouve à l'extérieur du canevas, ou n'est sur aucun élément, ce marqueur n'existe pas.

Les marqueurs permettent de modifier plusieurs éléments en même temps. Si, par exemple, on souhaite que tous les cercles aient la même couleur, mais que l'on veut pouvoir modifier celle-ci de temps en temps, il suffit d'affecter à tous les cercles le marqueur « cercle » au moment de leur création. La méthode itemconfigure permettra, ensuite, de modifier les options de configuration de tous les éléments ayant le marqueur "cercle".

Voici quelques exemples de la syntaxe employée pour créer des marqueurs :

 
Sélectionnez
$canevas->addtag("nouveau", "above", marqueur/id)

Le marqueur "nouveau" est ajouté à l'élément se trouvant au-dessus de celui référencé par marqueur ou id. S'il y en a plus d'un, le dernier élément trouvé sera utilisé afin que "nouveau" soit directement au-dessus de lui dans la liste d'affichage créée lorsque l'on ajoute des éléments au canevas. Cette dernière peut être manipulée avec les méthodes raise et lower.

 
Sélectionnez
$canevas->addtag("nouveau", "all");

Le mot-clé "all" est un marqueur spécial désignant tous les éléments du canevas. Les éléments ajoutés au canevas après l'appel à addtag ne seront pas concernés par le marqueur "nouveau".

 
Sélectionnez
$canevas->addtag("nouveau", "below", marqueur/id)

Le marqueur "nouveau" est ajouté à l'élément placé immédiatement en dessous de celui référencé par marqueur ou id. S'il y en a plus d'un, l'élément le plus à l'arrière-plan sera utilisé.

 
Sélectionnez
$canevas->addtag("nouveau", "closest", x,y)

Le marqueur "closest" sélectionne l'élément le plus proche des coordonnées x, y (du canevas). S'il y en a plusieurs, c'est le dernier trouvé qui sera choisi.

Si plusieurs éléments recouvrent le point indiqué, la méthode renverra le dernier ajouté. Pour indiquer la zone qui sera considérée comme « recouvrante », on ajoute un paramètre qui agrandira essentiellement la zone de recouvrement. Pour ajouter 10 pixels à cette zone, on écrira :

 
Sélectionnez
$canevas->addtag("nouveau", "closest", 50, 100, 10);

On peut également préciser un marqueur/identificateur de début de recherche. L'appel ressemble alors à :

 
Sélectionnez
$canevas->addtag("nouveau", "closest", x, y, 10, $mrq_ou_id);

Avec cette dernière forme, on peut passer en revue tous les éléments les plus proches.

 
Sélectionnez
$canevas->addtag("nouveau", "enclosed", x1,y1,x2,y2);

La forme "enclosed" de addtag permet d'assigner le même marqueur à plusieurs éléments se trouvant dans la zone délimitée par (x1,y1) et (x2,y2). Ceux-ci ne recevront le marqueur "nouveau" que s'ils sont entièrement dans la zone. Les coordonnées doivent être telles que x1 ≤ x2 et y1 ≤ y2.

 
Sélectionnez
$canevas->addtag("nouveau", "overlapping", x1,y1,x2,y2);

On utilisera "overlapping" au lieu de "enclosed" pour assigner des marqueurs à des éléments dont une partie se trouve à l'intérieur de la zone délimitée. Même si un seul pixel de l'élément se trouve dans celle-ci, il sera pris en compte. Les contraintes de coordonnées sont les mêmes que pour "enclosed".

 
Sélectionnez
$canevas->addtag("nouveau", "withtag", marqueur/id);

Assigne "nouveau" à tous les éléments ayant le marqueur ou l'identificateur indiqué.

IX-I-1. Liaison d'éléments à l'aide des marqueurs

Chaque élément d'un canevas peut être lié à une séquence d'événements afin qu'une fonction de rappel soit invoquée lorsque cette séquence arrive. Cette association ressemble à l'ajout d'une liaison à une séquence d'événements pour les widgets, mais on y utilise des marqueurs ou des identificateurs d'éléments. N'oubliez pas que, pour ajouter une liaison normale au canevas lui-même, il faut utiliser Tk::bind (ou canvasBind, si l'on utilise Tk8.0) à la place de bind.

La forme générale de cet appel est :

 
Sélectionnez
$canevas->bind(marqueur/id [ , séquence, commande ] );

séquence sera quelque chose comme "<Button-1>" ou "<Double-1>". Le chapitre 14, Liaisons d'événements, donne une définition et une explication complètes des séquences d'événements.

Lorsque l'on crée des liaisons d'éléments, on doit se rappeler que seules les liaisons souris et clavier sont reconnues. On ne peut pas se permettre toutes les liaisons ésotériques possibles pour les widgets.

Voici un exemple modifiant la couleur de n'importe quel élément ayant le marqueur "bleu" lorsque la souris est au-dessus de lui :

 
Sélectionnez
# Lorsque la souris est au-dessus de l'élément, on le colorie en bleu
$c->bind( "bleu", "<Enter>", sub { $c->itemconfigure( "bleu", -fill => "blue" ); } );

# Lorsque la souris est ailleurs, on le colorie en noir
$c->bind( "bleu", "<Leave>", sub { $c->itemconfigure( "bleu", -fill => "black" ); } );

IX-I-2. Recherche de marqueurs

La méthode find permet de connaître les éléments associés à un marqueur donné. Les différentes façons d'appeler find sont les mêmes que pour addtag (exception faite du paramètre "nouveau"). Voici quelques formes d'appels classiques (la section consacrée aux marqueurs, plus haut dans ce chapitre, détaille leur fonctionnement) :

 
Sélectionnez
$canevas->find("above", marqueur/id);
$canevas->find("all");
$canevas->find("below", marqueur/id);
$canevas->find("closest", x, y [ , zone_supplémentaire ] 
                               [ , marqueur/id ] ) ; 
$canevas->find("enclosed", x1, y1, x2, y2);
$canevas->find("overlapping", x1, y1, x2, y2);
$canevas->find("withtag", marqueur/id);

IX-I-3. Obtention des marqueurs d'un élément donné

Pour obtenir la liste de tous les marqueurs associés à un élément, on utilise l'instruction suivante :

 
Sélectionnez
@liste = $canevas->gettags(marqueur/id);

Si marqueur/id correspond à plusieurs éléments, le premier trouvé sera utilisé. Si la recherche échoue, la méthode renverra une chaîne vide.

IX-J. Coordonnées de la boîte de dimensionnement

Lorsque nous avons évoqué la zone de parcours d'un canevas, nous avons vu un exemple d'utilisation de la méthode bbox. Celle-ci renvoie une liste de quatre éléments qui définissent la zone dans laquelle se trouvent tous les marqueurs indiqués. L'exemple utilisait le marqueur spécial "all", qui désigne tous les éléments du canevas, pour définir la région de parcours, mais on peut préciser plusieurs marqueurs/id :

 
Sélectionnez
($gauche, $droite, $haut, $bas) = $canevas->bbox("bleu", "rouge");

En supposant que vous ayez assigné les marqueurs "bleu" et "rouge" aux éléments ayant ces couleurs, ce code renverra la région du canevas contenant tous les éléments bleus et rouges.

IX-K. Conversion de coordonnées

Lorsque l'on met en place une fonction de rappel et que l'on utilise les paramètres Ev('x') et/ou Ev('y') pour savoir où a cliqué l'utilisateur, on doit convertir cette information en coordonnées du canevas (Ev est expliqué au chapitre 14). Les méthodes canvasx et canvasy s'acquittent de cette tâche :

 
Sélectionnez
$x = $canevas->canvasx(x_écran [, maillage ] ); 
$y = $canevas->canvasy(y_écran [, maillage ] );

Les deux méthodes acceptent un paramètre optionnel permettant de préciser le maillage utilisé ; les coordonnées canevas seront alors arrondies à la valeur la plus proche convenant à ce maillage.

IX-L. Déplacement des éléments

Lorsqu'un élément a été créé dans le canevas, on peut le déplacer à l'aide des méthodes move ou coords. La première attend un marqueur ou un identificateur indiquant quels sont les éléments à déplacer et les montants à ajouter aux coordonnées x et y :

 
Sélectionnez
$canevas->move(marqueur/id, distance_x, distance_y);

Le code suivant, par exemple, déplacera les éléments portant le marqueur « bleu » de 100 pixels dans la direction x et de 100 pixels dans la direction y :

 
Sélectionnez
$canevas->move("bleu", 100, 100);

Pour déplacer un élément vers l'origine des axes, il suffit d'indiquer une valeur négative pour distance_x et/ou distance_y. L'autre méthode, coords, permet de préciser explicitement de nouvelles valeurs x et y pour le premier élément trouvé correspondant au marqueur ou à l'identificateur :

 
Sélectionnez
$canevas->coords(marqueur/id, nouveau_x, nouveau_y);

Si l'élément nécessite plusieurs paires de coordonnées, il suffit de les préciser :

 
Sélectionnez
$canevas->coords(marqueur/id, 
                 nouveau_x1, nouveau_y1, 
                 nouveau_x2, nouveau_y2, ...);

En utilisant coords sans indiquer de coordonnées, on peut aussi rechercher l'emplacement courant d'un élément dans le canevas :

 
Sélectionnez
@liste_coords = $canevas->coords(marqueur/id);

Rappelez-vous que la méthode coords ne s'applique qu'au premier élément qu'elle trouve et qui correspond au marqueur ou à l'identificateur indiqué.

IX-M. Modification de la liste d'affichage

À chaque fois qu'une méthode parcourt tous les éléments d'un canevas à la recherche d'un marqueur ou d'un identificateur donné, elle cherche dans la liste d'affichage modifiée à mesure que des éléments sont ajoutés au canevas. Le premier élément placé dans le canevas est aussi le premier de la liste et les suivants sont ajoutés dans leur ordre de création. Les derniers éléments ajoutés recouvrent les autres et sont donc tracés au-dessus d'eux. Les méthodes raise et lower permettent de modifier l'ordre d'affichage :

 
Sélectionnez
$canevas->raise(marqueur/id, dessus/id); 
$canevas->lower(marqueur/id, dessous/id);

Le premier paramètre de chaque méthode est le marqueur ou l'identificateur du ou des éléments que vous souhaitez déplacer dans la liste d'affichage. Le second est le marqueur ou l'identificateur de l'élément à côté duquel le premier doit être placé (soit au-dessus, soit en dessous). Si le premier marqueur ou identificateur correspond à plusieurs éléments, ceux-ci seront tous déplacés.

Si vous utilisez la méthode Scrolled pour créer le canevas, vous ne pourrez utiliser l'élément renvoyé par celle-ci pour invoquer raise ou lower :vous obtiendrez une déplaisante erreur à propos de types de paramètres incorrects, car Scrolled n'appelle pas cette version de raise ou lower, mais une autre. Utilisez Subwidget, comme dans l'exemple de la section « Utilisation de bind avec un canevasUtilisation de bind avec un canevas » , pour obtenir la référence au canevas afin de pouvoir appeler les versions voulues de ces méthodes.

IX-N. Suppression d'éléments

La méthode delete permet de supprimer définitivement un ou plusieurs éléments du canevas. Celle-ci attend une liste de marqueurs ou d'identificateurs comme paramètre : soyez prudent, car elle supprimera toutes les correspondances trouvées pour les marqueurs. Voici un exemple utilisant trois marqueurs/identificateurs distincts :

 
Sélectionnez
$canevas->delete("bleu", "cercle", $num_id);

On peut indiquer un seul marqueur/identificateur, ou autant que nécessaire.

IX-O. Suppression de marqueurs

La méthode dtag permet d'ôter des marqueurs des éléments. Elle est utilisable sous deux formes :

 
Sélectionnez
$canevas->dtag(marqueur); 
$canevas->dtag(marqueur/id, marqueur_à_ôter);

La première recherchera les éléments possédant le marqueur indiqué et leur ôtera alors celui-ci. La seconde recherchera les éléments possédant le marqueur ou l'identificateur indiqué et leur ôtera le marqueur marqueur_à_ôter (s'il existe). Cela vous permet de supprimer un sous-ensemble de marqueurs, plutôt que de répéter cette suppression sur chacun d'eux.

IX-P. Déterminer le type d'un élément

Pour déterminer le type d'un élément, on fait appel à la méthode type :

 
Sélectionnez
$canevas->type(marqueur/id);

Si le marqueur ou l'identificateur correspond à plus d'un élément, seul le type du premier est renvoyé. La valeur obtenue sera une chaîne rendant compte de son type : "oval", "text", "rectangle", etc.

IX-Q. Focus clavier

Pour donner le focus clavier à un élément, on utilise la méthode focus :

 
Sélectionnez
$canevas->focus(marqueur/id);

Si l'élément ne sait que faire du focus clavier, rien ne se passera.

IX-R. Représentation PostScript d'un canevas

La méthode postscript permet d'obtenir une copie PostScript d'un canevas. Elle renverra le PostScript produit ou, si l'option -file est utilisée, le placera dans le fichier indiqué et renverra une chaîne vide :

 
Sélectionnez
$postscript = $canevas->postscript(); 
$canevas->postscript(-file => "canevas.ps");

Vous pouvez contrôler la génération PostScript à l'aide des options suivantes :

-colormap => \@tableau

  • Chaque élément de @tableau doit être une commande PostScript permettant de configurer les couleurs, "1.0 1.0 0.0 setrgbcolor", par exemple.

-colormode => "color" | "gray" | "mono"

  • Crée le PostScript en couleurs, en nuances de gris ou en monochrome.

-file => nom_fichier

  • Précise le fichier dans lequel sera placé le code PostScript obtenu.

-fontmap => \@tableau

  • Chaque élément de @tableau doit être un tableau à deux éléments contenant un nom de fonte et une taille en points. Le nom de la fonte doit être un nom complet pour que Tk l'analyse correctement, "-*-Helvetica-Bold-O-Normal--*-140-*", par exemple.

-height => hauteur

  • Fixe la hauteur de la zone à imprimer. Par défaut, il s'agit de la hauteur du canevas.

-pageanchor => "n" | "e" | "s" | "w" | "center"

  • Indique où doit être placée la page sur le point de positionnement spécifié par les options -pagex et -pagey. Par défaut, elle sera centrée sur celui-ci.

-pageheight => hauteur

  • Fixe la hauteur de la page imprimée. La taille de l'image du canevas sera ajustée pour convenir à celle-ci. hauteur est exprimée en distances d'écran.

-pagewidth => largeur

  • Fixe la largeur de la page imprimée. La taille de l'image du canevas sera ajustée pour convenir à celle-ci.

-pagex => x

  • Configure l'abscisse du point de positionnement. x est exprimée en distances d'écran.

-pagey => y

  • Configure l'ordonnée du point de positionnement. y est exprimée en distances d'écran.

-rotate => 0 | 1

  • Si cette option vaut 1, la page est orientée en mode paysage. L'orientation par défaut est le mode portrait.

-width => largeur

  • Fixe la largeur de la zone du canevas qui sera imprimée. Par défaut, il s'agit de la largeur de celui-ci.

-x => x

  • Fixe le bord gauche de la zone à imprimer (en coordonnées du canevas). Par défaut, il s'agit du bord gauche de la fenêtre.

-y => y

  • Fixe le sommet de la zone à imprimer (en coordonnées du canevas). Par défaut, il s'agit du bord supérieur de la fenêtre.

IX-S. Modification de l'échelle d'un canevas

Lorsque l'on place un grand nombre d'éléments dans un canevas, il devient parfois difficile de tous les voir sans parcourir tout le widget. La méthode scale permet de modifier l'échelle d'un canevas pour que, par exemple, il réduise tout ce qu'il contient de moitié ou qu'il en double la taille. La syntaxe de cette méthode est la suivante :

 
Sélectionnez
$canevas->scale(marqueur/id, origine_x, origine_y, échelle_x, échelle_y);

L'échelle est centrée autour de origine_x et origine_y. Je vous conseille d'utiliser l'origine réelle (0, 0), sauf si vous trouvez une bonne raison de ne pas le faire. échelle_x et échelle_y sont les facteurs d'échelle utilisés sur les deux coordonnées de chaque élément. Voici quelques exemples :

 
Sélectionnez
$canevas->scale("all", 0, 0, 1, 1); # pas de changement ! 
$canevas->scale("all", 0, 0, .5, .5); # réduit tout de moitié 
$canevas->scale("all", 0, 0, 2, 2); # double tout 
$canevas->scale("all", 0, 0, 3, 3); # triple tout !

C'est une très bonne idée d'ajouter un bouton de grossissement et de réduction s'occupant pour vous de la mise à l'échelle. Conservez le facteur d'échelle dans une variable ($echelle, par exemple) et initialisez-la à 1. Multipliez-la par 0.5 pour réduire, et par 2 pour agrandir. Le dernier point à vérifier est que, si vous insérez de nouveaux éléments au canevas, les coordonnées de ceux-ci devront aussi être multipliées par le facteur d'échelle (sinon, ils apparaîtront trop grands ou trop petits, par rapport aux autres éléments du canevas).

IX-T. Recherche

La méthode scan implante la recherche dans un canevas :

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

Le premier appel mémorise les coordonnées x et y et la vue courante du canevas. Le second ajuste cette vue de 10 fois la différence entre les coordonnées indiquées et celles fournies à scanMark. Le canevas semblera alors être parcouru à très grande vitesse.

IX-T-1. Méthodes de parcours

On peut parcourir un widget canevas dans les deux directions : les méthodes xview et yview servent à communiquer avec les barres de défilement. Le chapitre 6 donne plus d'informations sur le fonctionnement de ces deux méthodes.

IX-U. Exemple de programme de dessin

Le widget canevas est bon à tout faire et peut servir à afficher différents types d'éléments. Lorsque l'on pense à un canevas, la première idée qui vient à l'esprit est celle d'un programme de dessin. Pour vous éviter ce travail, j'ai écrit un tel programme, rudimentaire : Quick Draw vous permet de tracer des rectangles, des ovales et des lignes. Vous pouvez également modifier l'épaisseur des objets avant de les dessiner. Voici son code :

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

my $mw = MainWindow->new;
$mw->title("Quick Draw");

my $f = $mw->Frame(
    -relief => 'groove',
    -bd     => 2,
    -label  => "Tracé :"
)->pack(
    -side => 'left',
    -fill => 'y'
);
my $element_trace = "rectangle";
$f->Radiobutton(
    -variable => \$element_trace,
    -text     => "Rectangle",
    -value    => "rectangle",
    -command  => \&liaison
)->pack( -anchor => 'w' );
$f->Radiobutton(
    -variable => \$element_trace,
    -text     => "Ovale",
    -value    => "ovale",
    -command  => \&liaison
)->pack( -anchor => 'w' );
$f->Radiobutton(
    -variable => \$element_trace,
    -text     => "Ligne",
    -value    => "ligne",
    -command  => \&liaison
)->pack( -anchor => 'w' );
$f->Label( -text => "Épaisseur de la ligne :" )->pack( -anchor => 'w' );
my $epaisseur = 1;
$f->Entry( -textvariable => \$epaisseur )->pack( -anchor => 'w' );
my $c = $mw->Scrolled( "Canvas", -cursor => "crosshair" )->pack(
    -side   => "left",
    -fill   => 'both',
    -expand => 1
);
my $canvas = $c->Subwidget("canvas");
my ( $debut_x, $debut_y );

liaison();

MainLoop;

sub liaison {

    # S'il y une liaison "Motion", il faut autoriser l'utilisateur
    # à terminer de tracer l'élément avant de lier à nouveau Button-1
    # Cette fonction sera appelée de nouveau lorsque le tracé sera
    # terminé.
    my @liaisons = $canvas->Tk::bind("<Motion>");
    return if ( $#liaisons >= 0 );
    if (   $element_trace eq "rectangle"
        || $element_trace eq "ovale"
        || $element_trace eq "ligne" )
    {
        $canvas->Tk::bind( "<Button-1>", [ \&debut_dessin, Ev('x'), Ev('y') ] );
    }
}

sub debut_dessin {
    my ( $canv, $x, $y ) = @_;
    $x = $canv->canvasx($x);
    $y = $canv->canvasy($y);

    # Petite vérification d'erreurs
    $epaisseur = 1 if ( $epaisseur !~ /[0-9]+/ );
    if ( $element_trace eq "rectangle" ) {
        $canvas->createRectangle(
            $x, $y, $x, $y,
            -width => $epaisseur,
            -tags  => "trace_moi"
        );
    }
    elsif ( $element_trace eq "ovale" ) {
        $canvas->createOval(
            $x, $y, $x, $y,
            -width => $epaisseur,
            -tags  => "trace_moi"
        );
    }
    elsif ( $element_trace eq "ligne" ) {
        $canvas->createLine(
            $x, $y, $x, $y,
            -width => $epaisseur,
            -tags  => "trace_moi"
        );
    }
    $debut_x = $x;
    $debut_y = $y;

    # Fait correspondre la liaison Button-1 à &fin_dessin
    # plutôt que de commencer à tracer
    $canvas->Tk::bind( "<Motion>",   [ \&taille_elt, Ev('x'), Ev('y') ] );
    $canvas->Tk::bind( "<Button-1>", [ \&fin_dessin, Ev('x'), Ev('y') ] );
}

sub taille_elt {
    my ( $canv, $x, $y ) = @_;
    $x = $canv->canvasx($x);
    $y = $canv->canvasy($y);
    $canvas->coords( "trace_moi", $debut_x, $debut_y, $x, $y );
}

sub fin_dessin {
    my ( $canv, $x, $y ) = @_;
    $x = $canv->canvasx($x);
    $y = $canv->canvasy($y);

    # finalise la taille de l'élément et ôte le marqueur
    $canvas->coords( "trace_moi", $debut_x, $debut_y, $x, $y );
    $canvas->dtag("trace_moi");

    # Supprime la liaison <Motion>
    $canvas->Tk::bind( "<Motion>", "" );
    liaison();
}

MainLoop;

On remarquera que je n'ai pas utilisé -scrollregion, car je souhaite créer un espace de dessin non limité (ne rien faire était la meilleure façon d'offrir cette possibilité !). Il s'agit d'un petit programme destiné à présenter l'utilisation de bind et de plusieurs méthodes du widget canevas. La figure 9.4 montre une copie d'écran de l'application après que plusieurs éléments ont été tracés.

IX-V. Essayez et amusez-vous !

L'application Quick Draw n'est pas très utile, mais elle donne des idées d'évolution :

  • ajouter la possibilité d'imprimer dans un fichier PostScript ;
  • créer une possibilité de sauvegarder le tracé en stockant le type et les coordonnées de chaque élément dans un fichier texte. Il faudra, bien sûr, ajouter aussi la possibilité de relire un tel fichier ;
  • ajouter la création d'éléments textuels ;
  • ajouter une zone de saisie permettant de modifier la couleur de tracé des éléments (en donnant un nom de couleur).

précédentsommairesuivant
Si vous disposez de Tk8.0, vous pouvez utiliser canvasBind au lieu de Tk::bind. J'utiliserai cette dernière tout au long de ce chapitre, mais notez que vous devriez plutôt utiliser canvasBind avec Tk8.0.
Cette expression permet de rendre compte d'un emplacement ou d'une direction en plaçant virtuellement l'interlocuteur debout sur l'axe d'un cadrant d'horloge à aiguilles et en lui indiquant l'heure où se trouverait alors l'objet à situer. L'expression « à trois heures » signifie donc « à droite », soit 0 degré, ici. Autres exemples : « À neuf heures » signifie « à gauche », et « À cinq heures » signifie « derrière, légèrement à droite ».

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.