Il existe un ensemble de méthodes pour dessiner
sur le "canevas" d'une zone de dessin. Ces méthodes peuvent être
utilisées pour n'importe quelle sous-classe de
gtk.gdk.Drawable
(soit un
gtk.gdk.Window
, soit un
gtk.gdk.Pixmap
). Les voici :
drawable.draw_point(gc
,x
,y
) # dessiner un point
...où gc
est le contexte graphique utilisé pour le dessin,
x
et y
sont les coordonnées du point.
drawable.draw_line(gc
,x1
,y1
,x2
,y2
) # dessiner une ligne
... où gc
est le contexte graphique.
x1
et y1
sont
les coordonnées du point de départ, x2
et
y2
les coordonnées du point d'arrivée.
drawable.draw_rectangle(gc
,filled
,x
,y
,largeur
,hauteur
) # dessiner un rectangle
... où gc
est le contexte graphique.
filled
est un booléen indiquant si le
rectangle doit être rempli avec la couleur de premier plan
(TRUE
) ou non (FALSE
).
x
et y
sont les
coordonnées du coin haut gauche du rectangle.
largeur
et
hauteur
indiquent la largeur et hauteur du
rectangle.
drawable.draw_arc(gc
,filled
,x
,y
,largeur
,hauteur
,angle1
,angle2
) # dessiner un arc de cercle
... où gc
est le contexte graphique.
filled
est un booléen indiquant si le
rectangle doit être rempli avec la couleur de premier plan
(TRUE
) ou non (FALSE
).
x
et y
sont les
coordonnées du coin haut gauche du rectangle inscrit. largeur
and hauteur
indiquent la largeur et hauteur du
rectangle inscrit.
angle1
est l'angle de départ de l'arc, en partant
de la position 3 heures, dans le sens inverse des aiguilles d'une montre,
par pas de 1/64 degré.
angle2
est la fin de l'angle de l'arc, relatif
à angle1
, par pas de 1/64 degré.
drawable.draw_polygon(gc
,filled
,points
) # dessiner un polygone
... où gc
est le contexte graphique.
filled
est un booléen indiquant si le
rectangle doit être rempli avec la couleur de premier plan
(TRUE
) ou non (FALSE
).
points
est un tuple contenant une liste de paires
de coordonnées, par exemple [ (0,0), (2,5), (3,7), (4,11) ], désignant les
point devant être reliés pour dessiner un polygone.
drawable.draw_string(font
,gc
,x
,y
,string
) # dessiner une chaîne de caractères drawable.draw_text(font
,gc
,x
,y
,string
) # dessiner un texte
... où font
est le
gtk.gdk.Font
utilisé pour dessiner la chaîne de caractères.
gc
est le contexte graphique.
x
et y
sont les
coordonnées du point où commence le dessin de la chaîne, c'est à dire, la ligne
de base de gauche.
string
est la chaîne de caractères à dessiner.
Les deux méthodes draw_string
() et
draw_text
() sont démodées. À la place, il faut
plutôt utiliser un pango.Layout
avec la méthode
draw_layout
().
drawable.draw_layout(gc
,x
,y
,layout
) # dessiner un affichage
... où gc
est le contexte graphique.
x
et y
sont les
coordonnées du point où débute le dessin du layout.
layout
est le
pango.Layout
qui va être dessiné.
drawable.draw_drawable(gc
,src
,xsrc
,ysrc
,xdest
,ydest
,largeur
,hauteur
) # dessiner un dessinable
... où gc
est le contexte graphique.
src
est le dessinable origine.
xsrc
and ysrc
are the
coordinates of the top left rectangle in the source drawable.
xdest
and ydest
sont les
coordonnées du coin haut gauche de la zone de dessin.
largeur
et hauteur
sont
la largeur et hauteur du dessinable d'origine à copier sur le
dessinable. Si l'un de ces paramètres vaut -1, on utilise la largeur ou
hauteur complète du dessinable.
drawable.draw_image(gc
,image
,xsrc
,ysrc
,xdest
,ydest
,largeur
,hauteur
) # dessiner une image
... où gc
est le contexte graphique.
image
est l'image origine.
xsrc
et ysrc
sont les
coordonnées du coin supérieur gauche du rectangle dans le dessinable source
xdest
et ydest
sont les
coordonnées du coin supérieur gauche dans la zone de dessin.
largeur
et hauteur
sont
la largeur et hauteur de la zone dessinable origine qui doit être
copiée sur le dessinable (drawable
). Si l'un de ces
paramètres vaut -1, on utilise la largeur ou hauteur complète de
l'image
.
drawable.draw_points(gc
,points
) # dessiner des points
... où gc
est le contexte graphique.
points
est une liste ou un tuple contenant
les tuples de paires de coordonnées, par exemple [ (0,0), (2,5), (3,7), (4,11) ]
désignant les points à dessiner.
drawable.draw_segments(gc
,segs
) # dessiner des segments de ligne
... où gc
est le contexte graphique.
segs
est une liste ou un tuple des coordonnées
des points de départ et de fin des segments à dessiner, contenues dans
un tuple, par exemple [ (0,0, 1,5), (2,5, 1,7), (3,7, 1,11), (4,11, 1,13) ]
drawable.draw_lines(gc
,points
) # dessiner une ligne brisée
... où gc
est le contexte graphique.
points
est une liste ou un tuple contenant
les tuples de paires de coordonnées, par exemple [ (0,0), (2,5), (3,7), (4,11) ]
désignant les points à relier par des lignes.
drawable.draw_rgb_image(gc
,x
,y
,largeur
,hauteur
,dith
,rgb_buf
,rowstride
) drawable.draw_rgb_32_image(gc
,x
,y
,largeur
,hauteur
,dith
,buf
,rowstride
) drawable.draw_gray_image(gc
,x
,y
,largeur
,hauteur
,dith
,buf
,rowstride
)
... où gc
est le contexte graphique.
x
et y
sont les coordonnées du coin supérieur gauche du rectangle qui contient
l'image.
largeur
and hauteur
sont
la largeur et la hauteur du rectangle qui contient l'image.
dith
est le mode de diffusion (tramage) décrit ci-dessous
Pour la méthode draw_rgb_image
(), le
paramètre rgb_buf
représente les données de l'image RGB,
codifiées dans une chaîne sous forme de séquence de triplets de pixels RGB de
8 bits. Pour la méthode draw_rgb_32_image
(),
buf
représente les données de l'image RGB,
codifiées dans une chaîne sous forme de séquence de triplets de pixels RGB de
8 bits avec 8 bits de padding (4 caractères par pixel RGB). Pour la
méthode draw_gray_image
(), buf
représente les données de l'image codifiées dans une chaîne de
pixels de 8 bits.
rowstride
est le nombre de caractères depuis le début
d'une rangée jusqu'au début de la rangée suivante de l'image. Normalement sa valeur
par défaut est 3 * largeur
pour la méthode
draw_rgb_image
(), 4 * largeur
pour la méthode draw_rgb_32_image
() et
largeur
pour la méthode draw_gray_image
().
Si rowstride
vaut 0, la ligne sera répétée
hauteur
fois.
Voici les différents modes de diffusion
(dither
) :
RGB_DITHER_NONE # Ne pas utiliser de diffusion. RGB_DITHER_NORMAL # Utiliser la diffusion si seulement 8 bits par pixels (ou moins). RGB_DITHER_MAX # Utiliser la diffusion si 16 bits par pixels (ou moins).
Le programme exemple drawingarea.py
illustre l'utilisation de la plupart des méthodes de la
DrawingArea
. Il place une zone de dessin
(DrawingArea
) dans une fenêtre défilante
ScrolledWindow
et ajoute des règles horizontales et
verticales (Ruler
). La Figure 12.1, « Exemple de Drawing Area »
montre le programme après lancement :
Le code source ci-dessous
drawingarea.py ci-dessous utilise l'image
pixmap gtk.xpm
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # exemple drawingarea.py 4 5 import pygtk 6 pygtk.require('2.0') 7 import gtk 8 import operator 9 import time 10 import string 11 12 class ExempleZoneDessin: 13 def __init__(self): 14 fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL) 15 fenetre.set_title("Exemple de zone de dessin") 16 fenetre.connect("destroy", lambda w: gtk.main_quit()) 17 self.zone_dessin = gtk.DrawingArea() 18 self.zone_dessin.set_size_request(400, 300) 19 self.stylepango = self.zone_dessin.create_pango_layout("") 20 self.fenetre_defil = gtk.ScrolledWindow() 21 self.fenetre_defil.add_with_viewport(self.zone_dessin) 22 self.table = gtk.Table(2,2) 23 self.reglehoriz = gtk.HRuler() 24 self.reglevert = gtk.VRuler() 25 self.reglehoriz.set_range(0, 400, 0, 400) 26 self.reglevert.set_range(0, 300, 0, 300) 27 self.table.attach(self.reglehoriz, 1, 2, 0, 1, yoptions=0) 28 self.table.attach(self.reglevert, 0, 1, 1, 2, xoptions=0) 29 self.table.attach(self.fenetre_defil, 1, 2, 1, 2) 30 fenetre.add(self.table) 31 self.zone_dessin.set_events(gtk.gdk.POINTER_MOTION_MASK | 32 gtk.gdk.POINTER_MOTION_HINT_MASK ) 33 self.zone_dessin.connect("expose-event", self.rappel_zone_dessin_expose) 34 def a_bouge(ruler, event): 35 return ruler.emit("motion_notify_event", event) 36 self.zone_dessin.connect_object("motion_notify_event", a_bouge, 37 self.reglehoriz) 38 self.zone_dessin.connect_object("motion_notify_event", a_bouge, 39 self.reglevert) 40 self.ajuste_hor = self.fenetre_defil.get_hadjustment() 41 self.ajuste_ver = self.fenetre_defil.get_vadjustment() 42 def rappel_valeur(ajuste, regle, horiz): 43 if horiz: 44 span = self.fenetre_defil.get_allocation()[3] 45 else: 46 span = self.fenetre_defil.get_allocation()[2] 47 l,u,p,m = regle.get_range() 48 v = ajuste.value 49 regle.set_range(v, v+span, p, m) 50 while gtk.events_pending(): 51 gtk.main_iteration() 52 self.ajuste_hor.connect('value-changed', rappel_valeur, self.reglehoriz, True) 53 self.ajuste_ver.connect('value-changed', rappel_valeur, self.reglevert, False) 54 def rappel_taille_fixee(wid, allocation): 55 x, y, w, h = allocation 56 l,u,p,m = self.reglehoriz.get_range() 57 m = max(m, w) 58 self.reglehoriz.set_range(l, l+w, p, m) 59 l,u,p,m = self.reglevert.get_range() 60 m = max(m, h) 61 self.reglevert.set_range(l, l+h, p, m) 62 self.fenetre_defil.connect('size-allocate', rappel_taille_fixee) 63 self.zone_dessin.show() 64 self.reglehoriz.show() 65 self.reglevert.show() 66 self.fenetre_defil.show() 67 self.table.show() 68 fenetre.show() 69 70 def rappel_zone_dessin_expose(self, zone_dessin, event): 71 self.style = self.zone_dessin.get_style() 72 self.contexte_graph = self.style.fg_gc[gtk.STATE_NORMAL] 73 self.trace_point(10,10) 74 self.trace_points(110, 10) 75 self.trace_ligne(210, 10) 76 self.trace_lignes(310, 10) 77 self.trace_segments(10, 100) 78 self.trace_rectangles(110, 100) 79 self.trace_arcs(210, 100) 80 self.trace_pixmap(310, 100) 81 self.trace_polygone(10, 200) 82 self.trace_image_rgb(110, 200) 83 return True 84 85 def trace_point(self, x, y): 86 self.zone_dessin.window.draw_point(self.contexte_graph, x+30, y+30) 87 self.stylepango.set_text("Point") 88 self.zone_dessin.window.draw_layout(self.contexte_graph, x+5, y+50, self.stylepango) 89 return 90 91 def trace_points(self, x, y): 92 points = [(x+10,y+10), (x+10,y), (x+40,y+30), 93 (x+30,y+10), (x+50,y+10)] 94 self.zone_dessin.window.draw_points(self.contexte_graph, points) 95 self.stylepango.set_text("Points") 96 self.zone_dessin.window.draw_layout(self.contexte_graph, x+5, y+50, self.stylepango) 97 return 98 99 def trace_ligne(self, x, y): 100 self.zone_dessin.window.draw_line(self.contexte_graph, x+10, y+10, x+20, y+30) 101 self.stylepango.set_text("Ligne") 102 self.zone_dessin.window.draw_layout(self.contexte_graph, x+5, y+50, self.stylepango) 103 return 104 105 def trace_lignes(self, x, y): 106 points = [(x+10,y+10), (x+10,y), (x+40,y+30), 107 (x+30,y+10), (x+50,y+10)] 108 self.zone_dessin.window.draw_lines(self.contexte_graph, points) 109 self.stylepango.set_text("Lignes") 110 self.zone_dessin.window.draw_layout(self.contexte_graph, x+5, y+50, self.stylepango) 111 return 112 113 def trace_segments(self, x, y): 114 segments = ((x+20,y+10, x+20,y+70), (x+60,y+10, x+60,y+70), 115 (x+10,y+30 , x+70,y+30), (x+10, y+50 , x+70, y+50)) 116 self.zone_dessin.window.draw_segments(self.contexte_graph, segments) 117 self.stylepango.set_text("Segments") 118 self.zone_dessin.window.draw_layout(self.contexte_graph, x+5, y+80, self.stylepango) 119 return 120 121 def trace_rectangles(self, x, y): 122 self.zone_dessin.window.draw_rectangle(self.contexte_graph, False, x, y, 80, 70) 123 self.zone_dessin.window.draw_rectangle(self.contexte_graph, True, x+10, y+10, 20, 20) 124 self.zone_dessin.window.draw_rectangle(self.contexte_graph, True, x+50, y+10, 20, 20) 125 self.zone_dessin.window.draw_rectangle(self.contexte_graph, True, x+20, y+50, 40, 10) 126 self.stylepango.set_text("Rectangles") 127 self.zone_dessin.window.draw_layout(self.contexte_graph, x+5, y+80, self.stylepango) 128 return 129 130 def trace_arcs(self, x, y): 131 self.zone_dessin.window.draw_arc(self.contexte_graph, False, x+10, y, 70, 70, 132 0, 360*64) 133 self.zone_dessin.window.draw_arc(self.contexte_graph, True, x+30, y+20, 10, 10, 134 0, 360*64) 135 self.zone_dessin.window.draw_arc(self.contexte_graph, True, x+50, y+20, 10, 10, 136 0, 360*64) 137 self.zone_dessin.window.draw_arc(self.contexte_graph, True, x+30, y+10, 30, 50, 138 210*64, 120*64) 139 self.stylepango.set_text("Arcs") 140 self.zone_dessin.window.draw_layout(self.contexte_graph, x+30, y+80, self.stylepango) 141 return 142 143 def trace_pixmap(self, x, y): 144 pixmap, mask = gtk.gdk.pixmap_create_from_xpm( 145 self.zone_dessin.window, self.style.bg[gtk.STATE_NORMAL], "gtk.xpm") 146 147 self.zone_dessin.window.draw_drawable(self.contexte_graph, pixmap, 0, 0, x+15, y+25, 148 -1, -1) 149 self.stylepango.set_text("Pixmap") 150 self.zone_dessin.window.draw_layout(self.contexte_graph, x+5, y+80, self.stylepango) 151 return 152 153 def trace_polygone(self, x, y): 154 points = [(x+10,y+60), (x+10,y+20), (x+40,y+70), 155 (x+30,y+30), (x+50,y+40)] 156 self.zone_dessin.window.draw_polygon(self.contexte_graph, True, points) 157 self.stylepango.set_text("Polygone") 158 self.zone_dessin.window.draw_layout(self.contexte_graph, x+5, y+80, self.stylepango) 159 return 160 161 def trace_image_rgb(self, x, y): 162 b = 80*3*80*['\0'] 163 for i in range(80): 164 for j in range(80): 165 b[3*80*i+3*j] = chr(255-3*i) 166 b[3*80*i+3*j+1] = chr(255-3*abs(i-j)) 167 b[3*80*i+3*j+2] = chr(255-3*j) 168 buff = string.join(b, '') 169 self.zone_dessin.window.draw_rgb_image(self.contexte_graph, x, y, 80, 80, 170 gtk.gdk.RGB_DITHER_NONE, buff, 80*3) 171 self.stylepango.set_text("Image RGB") 172 self.zone_dessin.window.draw_layout(self.contexte_graph, x+5, y+80, self.stylepango) 173 return 174 175 def main(): 176 gtk.main() 177 return 0 178 179 if __name__ == "__main__": 180 ExempleZoneDessin() 181 main()