Tcl / Tk
Le widget canvas de Tk
Auteur :
Arnaud LAPREVOTE
Linbox Free&ALter Soft
152, rue de Grigy
57070 METZ
tel: 03 87 50 87 90 - 06 11 36 15 30
fax : 03 87 75 19 26
Email : arnaud.laprevote@linbox.com
1. Le widget canvas
Une note d'avertissement pour le lecteur. Je viens de finir à l'instant "Métaphysique des tubes" d'Amélie Nothomb. J'en sors enthousiaste et réjouis. Malheureusement pour le lecteur de cette prose, j'ai une tendance naturelle à être un caméléon. Résultat, mon style va se ressentir de cette lecture. Malheureusement, je n'ai ni le talent ni le style de cet auteur. Le pire est donc à craindre.Généralement, l'on apprend à dessiner avant d'apprendre à écrire. Dans le cas d'espèce, nous allons faire l'inverse et dessiner après avoir écrit. Tant pis, ou tant mieux.
Le widget canvas est une surface sur laquelle vous pouvez disposer et manipuler toute sorte d'objets graphiques :
- des lignes,
- des suites de lignes,
- des ellipses,
- des courbes,
- des rectangles,
- des zones de texte,
- des images ou des bitmaps,
- des fenêtres embarquées contenant tout autre widget.
On retrouve le mécanisme des tags, qui permettait de manipuler un objet ou des ensembles d'objet dans le widget texte. Tout comme avec le widget text, je ne prétends pas à l'exhaustivité dans le traitement du widget canvas. Si vous pensez qu'une fonction ou une option doit ou devrait exister, reportez-vous à la description du canvas pour en être sûr.
Le canvas est une liste dans l'ordre d'apparition des objets graphiques que l'on y dessine. L'on peut changer les caractéristiques d'un élément, ou changer l'ordre d'apparition des objets dans la liste. Un élément est dessiné au-dessus des éléments déssinés antérieurement.
2. Quelques élucubrations générales
Les différents objets ont des caractéristiques communes. Quelques unes sont données ci-dessous.| Option | Signification |
| -dash forme de pointillé | Lorsque des traits sont utilisés, ils peuvent représenter des pointillés. L'option permet de choisir le type de pointillé. Par exemple {2 4} ou .- |
| -activedash forme de pointillé | Le pointillé pour un trait actif |
| -disableddash forme de pointillé | Le pointillé pour un trait non actif |
| -dashoffset nombre | L'offset au démarrage du pointillé |
| -fill couleur | Couleur de remplissage |
| -activefill couleur | Couleur de remplissage si actif |
| -disabledfill couleur | Couleur de remplissage si inactif |
| -stipple bitmap | Un motif bitmap utilisé pour le remplissage |
| -activestipple bitmap | Un motif bitmap utilisé pour le remplissage d'un objet actif |
| -disabledstipple bitmap | Un motif bitmap utilisé pour le remplissage d'un objet inactif |
| -state normal/hidden/disabled | L'état normal, caché ou non activé d'un objet |
| -tag tag/liste de tags | Tag permettant de regrouper ou de nommer un ou plusieurs objets |
| -width largeur | Largeur en pixels |
| -activewidth largeur | Largeur si actif |
| -disabledwidth largeur | Largeur si inactif |
Nous avons évoqué dans ce qui précède une mystérieuse forme de pointillé, elle dispose de 2 syntaxes. L'une est à base d'un des 5 signes [.,-_ ]. L'autre utilise une liste de nombres. Un nombre sur 2 représente le nombre de pixels d'une ligne, l'autre le nombre de pixels transparents suivant. La liste est donc un nombre pair de nombres permettant de créer des motifs d'une grande complexité.
Chaque objet graphique est identifiable de 2 manières. A la création d'un objet un numéro d'identification est créé :
canvas .can -width 300 -height 200 pack .can .can create line 100 50 200 50
A l'exécution de cet exemple, la valeur
1est retournée. C'est le numéro de carte d'itentité (nouveau type infalsifiable merci Charles) de la ligne (blanche à ne pas franchir, merci Charles). On peut systématiquement utiliser l'identité ou le tag d'un élément graphique. Le tag doit obligatoirement commencer par une lettre pour ne pas être confondu avec un numéro d'identité.
Non seulement il est possible de définir des tags à la création des objets graphiques, mais en plus 2 sont définis par défaut. Le tag all contient tous les objets graphiques de la page. Le tag current indique l'élément graphique le plus haut et le plus proche de la souris.
Grâce au tag d'un élément graphique, il est possible de connaître et de configurer chacune de ses caractéristiques. On connait une caractéristique d'un élément grâce à :
.can itemcget tag optionPar exemple :
canvas .can -width 300 -height 200 pack .can .can create line 100 50 200 50 200 150 100 \ 150 100 50 -arrow both -tag this_line .can itemcget this_line -arrowLa dernière instruction renvoie
both
Il est possible de changer une caractéristique d'un élément grâce à la commande itemconfigure. d'où par exemple :
.can itemconfigure this_linequi renvoie :
{-arrow {} {} none both} {-arrowshape {} {} {8 10 3} {8 10 3}} {-capstyle {} {} butt butt} {-fill {} {} black black} {-joinstyle {} {} round round} {-smooth {} {} 0 0} {-splinesteps {} {} 12 12} {-stipple {} {} {} {}} {-tags {} {} {} this_line} {-width {} {} 1 1}
On peut modifier la largeur du trait de la manière suivante :
.can itemconfigure this_line -width 5
On peut obtenir les coordonnées d'un élément avec la commande coords, et l'on peut bouger un élément avec la commande move.
canvas .can -width 300 -height 200 pack .can .can create line 100 50 200 50 200 150 100 \ 150 100 50 -arrow both -tag this_line .can coords this_line
On obtient alors :
100.0 50.0 200.0 50.0 200.0 150.0 100.0 150.0 100.0 50.0
On peut obtenir un déplacement de l'élément grâce à :
.can move this_line 10 20Ob obtient alors un déplacement de 10 pixels vers la droite et de 20 pixels vers le bas.
3. Tirons une ligne, un point c'est tout
Une ligne est créée par la commande :.canvas create line x0 y0 x1 y1 x2 y2 ... xn yn ?option valeur ?option valeur ...
D'où par exemple :
canvas .can -width 300 -height 200 pack .can .can create line 100 50 200 50 200 150 100 \ 150 100 50 .can create line 110 60 190 60 190 140 110 \ 140 110 60 -smooth 1 -fill "#0000FF" .can itemconfigure 2 -arrow both

Comme vous pouvez le constater, cette commande permet de créer aussi bien une ligne, qu'une suite de ligne, que des courbes (options -smooth 1).
4. Si c'est rond, ...
Les ellipses sont créées par la commande :.canvas create oval x1 y1 x2 y2 ?option valeur ?option valeur ...
x1 y1 x2 y2 donne les 2 coins opposés d'un rectangle dans lequel l'oval s'inscrit.
canvas .can -width 300 -height 200 -background "#E0FFE0" pack .can .can create oval 50 50 150 150 -width 10 .can create oval 80 80 120 120 -fill "#ff0000" .can create oval 160 50 300 80 -outline "#00ff00" \ -width 5 -fill "#ffffff"

5. Aux arcs citoyens
Un arc est une portion d'ellipse. Cette portion d'ellipse part d'un angle donné, et s'étend sur une portion de l'ellipse. 3 styles d'arcs existent :- -style pieslice : portion de camembert,
- -style chord : une portion d'arc dont les extrémités sont reliées par une ligne,
- -style arc : simplement la ligne d'arc.
La création de l'arc utilise la commande :
.can create arc x0 y0 x1 y1 ?-option1 valeur1 -option2 valeur2 ...?
D'où l'exemple suivant :
canvas .can -width 300 -height 200 -background "#E0FFE0"
pack .can
.can create arc 50 50 100 100 -style pieslice \
-start 0 -extent 90
.can create arc 110 50 160 100 -style chord \
-start 90 -extent 90 -fill "#ffff00" -width 5 \
-outline "#00ffff"
.can create arc 50 110 100 160 -style arc \
-start 180 -extent 90 -outline "#808080"
.can create arc 110 110 160 160 -style pieslice \
-start 270 -extent 90
.can create line 0 50 300 50
.can create line 0 100 300 100
.can create line 0 110 300 110
.can create line 0 160 300 160
.can create line 50 0 50 200
.can create line 100 0 100 200
.can create line 110 0 110 200
.can create line 160 0 160 200

6. Tu polygones ?
Un polygone est une figure fermée. Les côtés du polygone peuvent être droits ou courbes (splines). Le polygone peut être plein ou vide. A partir du moment où l'on utilise un polygone, le premier et le dernier point sont reliés entre eux.La syntaxe est la suivante :
.can create polygon x1 y1 ... xn yn ?option valeur option valeur?
Les options des polygones sont les suivantes :
- -smooth [0|1] : transformation en spline des lignes droites,
- -splinesteps [entier] : nombre de segments utilisés pour approximer les splines.
D'où l'exemple suivant :
# Creating a new canvas
canvas .can -width 300 -height 200 -background "#E0FFE0"
# Putting some frames for buttons below
frame .button_frame
# This button will allow to switch between smooth 1 and smooth 0
button .button_frame.smooth_button -text "Smooth" -command {
set smooth [.can itemcget poly1 -smooth]
.can itemconfigure poly1 -smooth [expr 1 - $smooth]
}
pack .button_frame.smooth_button
pack .can .button_frame -side top
.can create polygon 100 10 150 20 160 50 150 100 \
130 120 90 130 40 100 70 70 80 60 70 50 -tag poly1
# Inside of polygon will be white
.can itemconfigure poly1 -fill "#ffffff"
# Color of the line delimiting the polygon
.can itemconfigure poly1 -outline "#000000"
Qui permet d'obtenir les figures suivantes :
|
|
|
7. Jouons aux 4 coins
Zou un trivial rectangle :.can create rectangle x0 y0 x1 y1 ?option valeur option valeur?
Donc :
# Creating a new canvas canvas .can -width 300 -height 200 -background "#E0FFE0" pack .can .can create rectangle 10 10 100 100 -outline "#000000" -fill "#ffffff" -width 4 -tags rect1Donnant :

N'oubliez pas que vous pouvez obtenir toutes les options en regardant la documentation du canvas ou en demandant le man canvas.
8. Le poids des mots
Détendez-vous, ils ont fait simple..can create text x0 y0 ?option valeur option valeur ...?
Les options les plus courantes sont :
- -anchor [left|center|right] : permet de donner la position du texte par rapport au point de positionnement,
- -font nomdelafonte : la fonte,
- -justify [left|center|right] : justification du texte à l'intérieur des limites de la boite d'affichage. N'est utile que si le texte est sur plusieurs lignes,
- -text chaine_a_afficher : la chaîne à afficher,
- -width largeur_de_la_fenetre : largeur de la fenêtre d'affichage.
# Creating a new canvas canvas .can -width 300 -height 200 -background "#E0FFE0" pack .can # Creating a font font create font0 -family Helvetica -size 20 -weight bold # And now a text .can create text 150 150 -anchor center -font font0 -justify center -text "Ceci est un texte" -width 200

9. Le choc des photos
Il est trivial d'ajouter des photos dans un canvas. Tout d'abord on crée un bitmap ou une photo, puis on la place sur le canvas..can create image x0 y0 -image une_image
Les options disponibles sont :
- -anchor [n|e|w|s|ne|...|center] : position de l'image par rapport au point d'ancrage,
- -image nom_de_l_image : nom de l'image précédemment créée avec la commande image create.
Une exemple possible est :
# Creating a new canvas canvas .can -width 300 -height 200 -background "#E0FFE0" pack .can # Chargement d'une image image create photo exemple1 -file img/exemple.gif # Affichage de l'image .can create image 160 110 -image exemple1Donnant pour résultat :

10. Le noir et blanc c'est dépassé
Les bitmaps sont une catégorie d'images noire et blanc utilisées pour le curseur par exemple. Cela date un peu mais un type particulier existe en tcl/tk..can create bitmap x0 y0 ?option valeur option valeur?
Les options courantes sont :
- -bitmap nom_d_un_bitmap : le nom d'un bitmap à charger,
- -anchor [n|e|w|s|ne|nw|...|center] : la position du bitmap par rapport au point d'ancrage,
- -background couleur : la couleur des pixels de fond,
- -foreground couleur : la couleur des pixels d'avant plan,
- -tags list_de_tag : liste de tags associée au bitmap.
Un exemple possible est en utilisant les bitmaps standards de tcl le suivant :
# Creation d'un nouveau canvas
canvas .can -width 300 -height 200 -background "#E0FFE0"
pack .can
# Affichage des bitmaps
set xori 80
set yori 40
set incx 40
set incy 80
set width 240
set x $xori
set y $yori
# Creating a serie of bitmap in the canvas.
# Foreach one a different anchor is used
# (respectively n e w s ne nw se center),
# different foreground and background are also used.
foreach bitmap [list error gray25 gray50 hourglass \
info questhead question warning] \
anchor [list n e w s ne nw se center] \
background [list "#000000" "#ff0000" "#00ff00" \
"#0000ff" "#ffff00" "#00ffff" "#ff00ff" "#ffffff"] \
foreground [list "#ffffff" "#ff00ff" "#00ffff" \
"#ffff00" "#0000ff" "#00ff00" "#ff0000" "#000000"] {
.can create bitmap $x $y -bitmap $bitmap -anchor $anchor \
-background $background -foreground $foreground
.can create text $x [expr $y - 30] -text "$anchor" \
-anchor center
incr x $incx
if { $x > $width } {
set x $xori
incr y $incy
}
}

11. Des fenêtres dans les canevas
Finalement, il est possible d'insérer des fenêtres dans les canevas pour insérer d'autres widgets. Cette possibilité rend assez simple en tcl la création de nouveaux widgets comme le notebook, ou des trames nommés (named frame), ou des frame à tailles variables, ... L'imagination est maître dans ce cas.On utilise pour cela l'objet window. Et cela se fait de la manière suivante :
.can create window x0 y0 -widget .can.widget
Les options standards sont :
- -window .nom.du.widget : le widget que l'on veut inclure,
- -anchor [n|e|w|s|ne|nw|...|center] : position de la fenêtre par rapport au point d'ancrage,
- -width largeur : largeur de la fenêtre,
- -height hauteur : hauteur de la fenêtre,
- -tags liste_de_tags : liste de tags associés à la fenêtre.
Nous allons reprendre l'exemple concernant les polygones mais en insérant 2 boutons directement dans le canvas.
# Creation du nouveau canvas
canvas .can -width 300 -height 200 -background "#E0FFE0"
# Creation d'une frame pour les boutons
frame .can.button_frame
# Ce bouton permet de basculer de smooth 0 a 1
button .can.button_frame.smooth_button -text "Smooth" -command {
set smooth [.can itemcget poly1 -smooth]
.can itemconfigure poly1 -smooth [expr 1 - $smooth]
}
pack .can.button_frame.smooth_button
pack .can
.can create polygon 100 10 150 20 160 50 150 100 \
130 120 90 130 40 100 70 70 80 60 70 50 -tag poly1
# L'intérieur du polygone sera blanc
.can itemconfigure poly1 -fill "#ffffff"
# Couleur de la ligne autour du polygone
.can itemconfigure poly1 -outline "#000000"
# Insertion de la frame
.can create window 200 150 -window .can.button_frame \
-width 90 -anchor w






