LE CANVAS
Le canvas est un widget très puissant qui vous permet de dessiner, afficher une image, de créer de nouveaux widgets et bien d'autres choses encore.
Cette page relativement longue, voici des liens rapides pour accéder directement aux rubriques :
Voici des tutoriels puisés sur internet qui regorgent d'exemples sur ce widget:
Le canvas peut être simplement créé avec la commande :
canvas .cv
Il possède de nombreuses options qui vous permettent de lui attribuer des propriétés comme sa largeur, sa hauteur etc..
Par exemple pour lui donner la taille de 50 pixels de large par 70 pixels de haut écrivez ceci :
canvas .cv -width 50 -height 70
Pour le fond d'écran écrivez ceci :
canvas .cv -width 50 -height 70 -bg #FF0000
dessiner une image dans un canvas
Cet exemple vous détaille comment afficher une image dans un Canvas.
Voici le code de cet exemple :
package require Img image create photo img -file "tatras.jpg" set height [image height img] set width [image width img] canvas .can -height $height -width $width .can create image 0 0 -anchor nw -image img pack .can wm title . "High Tatras" wm geometry . +300+300
Tout d'abord pour pouvoir afficher une image dans un Canvas , il vous faut télécharger la librairie tkimg et tkpng depuis vos dépots.
Ensuite voici les étapes essentielles :
Une petite remarque intéressante qui n'a rien à voir avec le Canvas dans ce code:
Il est définit la géometrie (c'est à dire la taille et disposition de la fenêtre) par la commande
wm.geometry . +300+300
Seule la taille est définit et non le placement
Dessiner une fonction mathematique (arbre avec des lignes)
Cet exemple utilise la fonction SINUS et COSINUS ainsi que le nombre PI (arrondi à 7 chiffres après la virgule.
Voici comment réaliser cet arbre :
pack [canvas .c -width 400 -height 300 -bg white]
proc drawBranch {xstart ystart length angle rgb} {
# Compose the colour foreach {red green blue} $rgb {break} set colour [format "#%2.2x%2.2x%2.2x" $red $green $blue] # Determine the end point set phi [expr {$angle * 3.1415926 / 180.0}] set xend [expr {$xstart + $length * cos($phi)}] set yend [expr {$ystart + $length * sin($phi)}] # The line thickness set width 3 if { $length < 25 } { set width 2 } if { $length < 5 } { set width 1 }
# Draw the branch and the sub-branches
.c create line $xstart $ystart $xend $yend -fill $colour -width $width if { $length > 1.0 } { set rgbLeft [list [expr {int(0.8*$red)}] $green $blue] set rgbRight [list $red $green [expr {int(0.8*$blue)}]] set angleLeft [expr {$angle + 45.0}] set angleRight [expr {$angle - 45.0}] set length [expr {2.0*$length/3.0}] drawBranch $xend $yend $length $angleLeft $rgbLeft drawBranch $xend $yend $length $angleRight $rgbRight } } drawBranch 200 280 100 270 {255 0 255}
Une procédure drawBranch est créée pour réaliser cet arbre.
Cet exemple montre comment dessiner une ligne (code en rouge)
Remplir des formes avec une couleur de fond
Dans cet exemple nous allons remplir 3 carrés avec des couleurs différentes.
Téléchargez le fichier source ICI
Voici le code :
canvas .can .can create rect 30 10 120 80 -outline #fb0 -fill #fb0 .can create rect 150 10 240 80 -outline #f50 -fill #f50 .can create rect 270 10 370 80 -outline #05f -fill #05f pack .can wm title . "Couleurs" wm geometry . 400x100+300+300
Rien de compliqué dans cet exemple, je pense que vous aurez vite compris.
-outline correspond au contour
-fill correspond à l'intérieur
DEssiner du texte dans un canvas
Dans cet exemple nous allons écrire du texte dans un Canvas.
Voici le code :
canvas .can .can create text 10 30 -anchor w -font Purisa -text "Most relationships seem so transitory" .can create text 10 60 -anchor w -font Purisa -text "They're good but not the permanent one" .can create text 10 110 -anchor w -font Purisa -text "Who doesn't long for someone to hold" .can create text 10 140 -anchor w -font Purisa -text "Who knows how to love without being told" .can create text 10 170 -anchor w -font Purisa -text "Somebody tell me why I'm on my own" .can create text 10 200 -anchor w -font Purisa -text "If there's a soulmate for everyone" pack .can -fill both wm title . "lyrics" wm geometry . 430x250+300+300
Ce qu'il faut retenir dans cet exemple :
exemple concret : partition musicale
Pour mettre en application tout ce que nous avons découvert précédemment, nous allons réaliser une partition musicale.
Lorsque nous tapons une lettre au clavier, elle est converti en une note affichée sur la partition :
Le code étant très long dans le fichier, la mise en page de cette page serait non lisible.
Je mets le code uniquement en téléchargement ci-dessus et non affiché ici.
evenements du canvas
Maintenant que nous avons étudié comment dessiner toutes sortes de formes, il est intéressant de faire réagir aux évènements clavier souris notre application.
Nous allons voir ci-dessous deux exemples pour déplacer des formes dans un canvas.
Cet exemple est très intéressant. Il permet de faire bouger deux formes (un rond et une ligne) dans un Canvas.
Voici le code :
proc moveit {object x y} { .c coords $object [expr $x-25] [expr $y-25] [expr $x+25] [expr $y+25] } canvas .c -width 250 -height 100 set myoval [.c create oval 0 0 50 50 -fill orange] 'Crée un objet Ovale set myline [.c create line 50 50 100 100 -fill blue -width 4] 'Crée un objet ligne .c bind $myoval<1> {moveit $myoval %x %y} 'Evènement à un clic gauche sur l'ovale .c bind $myline <1> {moveit $myline %x %y} 'Evènement à un clic gauche sur la ligne grid .c -row 0 -column 0
Commentons ce code :
Les caractères en rouge ne sont là que pour expliquer et doivent être effacés pour exécuter ce code.
On crée 2 objets myoval et myline qui lors d'un clic gauche lanceron la procédure moveit.
Cette procédure a 3 paramètres:
Pourquoi -25 et +25 me direz-vous? regardez la taille de l'ovale ou la ligne ce sont des multiples de 50.
Si vous définissez une autre valeur, l'ovale ou la ligne auront des déformations lors du déplacement.
Un autre exemple pour déplacer une forme sur deux fenêtres différentes en même temps.
Ce petit exemple est tout simplement bleuffant !
Quand vous déplacez le rond bleu, il se déplace à l'identique dans l'autre fenêtre.
Le mode echo vous permet même d'effectuer un ralenti.
Pour résumer, voici de manière générale l'écriture d'un évènement sur un canvas :
.can bind $id <1> {puts "action à réaliser"}
ou :
Changer un texte deja dessine
Je crée un canvas et j'y insère un texte par le code suivant :
set wtext [.cv create text 20 12 -anchor w -font "Serif 9" -text "Title"]
Si je souhaite changer le texte, il suffit d'utiliser l'option itemconfigure comme ceci :
.cv itemconfigure $wtext -text "Mon nouveau texte"
redimensionner un canvas en meme temps que la fenetre
Problème :
Je souhaite dessiner un Carré dans un canvas qui est à 20 pixels à l'intérieur, et quand je redimensionne la fenêtre par son coin inférieur à droite, je souhaite que le carré suivent les bords du canvas et de la fenêtre.
Le redimensionnement d'une fenêtre en Tk réagit à l'évènement
Nous pouvons donc écrire le code suivant :
toplevel .tl pack [canvas .tl.can] -fill both -expand 1 set id [.tl.can create rect 20 20 300 300 -outline #000000] bind .tl.can <Configure> [list resizeRect %W %w %h $id] proc resizeRect {canv width height id} { set x1 20; set y1 20 set x2 [expr {$width - 21}] if {$x2 < $x1} { set x2 $x1 } set y2 [expr {$height - 21}] if {$y2 < $y1} { set y2 $y1 } $canv coords $id $x1 $y1 $x2 $y2 }
grouper des formes ensemble pour reagir au même evenement (utilsation des tags)
Vous avez compris que je peux déclencher un évènement à l'aide de la commande bind sur un dessin ou widget contenu dans le canvas.
Mais il est aussi possible de définir des TAGS, c'est à dire une étiquette rassemblant les dessins dans un même groupe.
(en construction)