Hay un conjunto general de métodos que se pueden usar para dibujar
en el área de dibujo. Estos métodos de dibujo funcionan en cualquier
gtk.gdk.Drawable (Dibujable), que es una
gtk.gdk.Window (Ventana) o un
gtk.gdk.Pixmap (Mapa de Píxeles). Los métodos de dibujo
son:
drawable.draw_point(gc,x,y) # dibuja_punto
gc es el Contexto Gráfico que se usará para hacer el
dibujo.
x e y son las coordenadas del
punto.
drawable.draw_line(gc,x1,y1,x2,y2) # dibuja linea
gc es el Contexto Gráfico.
x1 e y1 especifican el punto
de inicio de la linea. x2 e y2
especifican el punto final de la linea.
drawable.draw_rectangle(gc,filled,x,y,width,height) # dibuja rectángulo
gc es el Contexto Gráfico.
filled es un valor booleano que indica si el
rectángulo debe ser rellenado con el color de primer plano (valor TRUE) o no (valor FALSE).
x e y son las coordenadas de
la esquina superior izquierda del rectángulo.
width y height son el ancho
y el alto del rectángulo.
drawable.draw_arc(gc,filled,x,y,width,height,angle1,angle2) # dibuja arco
gc es el Contexto Gráfico.
filled es un valor booleano que indica si el
arco debe ser rellenado con el color de primer plano (valor TRUE) o no (valor FALSE).
x e y son las coordenadas de
la esquina superior izquierda del rectángulo que bordea al arco. width y height son el ancho y el alto
del rectángulo que bordea al arco.
angle1 es el ángulo inicial del arco, relativo
a la posición de las 3 en punto del reloj, en el sentido contrario de las
agujas del reloj, en sesenta y cuatroavos de grado.
angle2 es el ángulo final del arco, relativo a
angle1, en sesenta y cuatroavos de grado en el sentido de
las agujas del reloj.
drawable.draw_polygon(gc,filled,points) # dibuja polígono
gc es el Contexto Gráfico.
filled es un valor booleano que especifica si
el polígono debe ser rellenado con el color de primer plano o(valor TRUE) o no (valor FALSE).
points es una lista de los puntos que se van a dibujar como un polígono conectado, escrita como una lista de tuplas con las coordenadas, como por ejemplo: [ (0,0), (2,5), (3,7), (4,11) ].
drawable.draw_string(font,gc,x,y,string) # dibuja cadena drawable.draw_text(font,gc,x,y,string) # dibuja texto
font es la gtk.gdk.Font
(fuente) que se usará para pintar la cadena.
gc es el Contexto Gráfico.
x e y son las coordenadas del
punto donde se empezará a dibujar la cadena, es decir, la línea base
izquierda.
string es la cadena de caracteres a dibujar.
Ambos métodos draw_string() y
draw_text() están obsoletos - en su lugar se debe usar un
pango.Layout con el método
draw_layout() .
drawable.draw_layout(gc,x,y,layout) # dibuja disposición
gc es el Contexto Gráfico.
x e y son las coordenadas
del punto desde el que se empieza a dibujar la disposición.
layout es el pango.Layout
que se va a dibujar.
drawable.draw_drawable(gc,src,xsrc,ysrc,xdest,ydest,width,height) # dibuja dibujable
gc es el Contexto Gráfico.
src es el dibujable de orígen.
xsrc e ysrc son las
coordenadas de la esquina superior izquierda del rectángulo en el dibujable de
orígen.
xdest e ydest son las
coordenadas de la esquina superior izquierda en el área de dibujo.
width y height son el ancho
y el alto del área del dibujable de origen que será copiada al dibujable
(drawable). Si width o
height es -1 entonces se usará el ancho o el alto total del
dibujable.
drawable.draw_image(gc,image,xsrc,ysrc,xdest,ydest,width,height) # dibuja imagen
gc es el Contexto Gráfico.
image es la imagen de origen.
xsrc e ysrc son las
coordenadas de la esquina superior izquierda del rectángulo en el dibujable
origen.
xdest e ydest son las
coordenadas de la esquina superior izquierda del rectángulo en el área de
dibujo.
width y height son el ancho
y el alto del área del dibujable origen que se copiará en el dibujable (drawable) destino. Si width o height es -1 entonces se usará el ancho o el alto total de la imagen.
drawable.draw_points(gc,points) # dibuja puntos
gc es el Contexto Gráfico.
points es una lista o tupla de pares de
coordenadas en tuplas, por ejemplo [ (0,0), (2,5), (3,7), (4,11) ], que representa la lista de los
puntos que se deben dibujar.
drawable.draw_segments(gc,segs) # dibuja segmentos
gc es el Contexto Gráfico.
segs es una lista o tupla de tuplas que representan las
coordenadas de los puntos iniciales y finales de los segmentos que se quiere dibujar, tal como: [ (0,0, 1,5), (2,5, 1,7), (3,7, 1,11), (4,11, 1,13) ] .
drawable.draw_lines(gc,points) # dibuja lineas
gc es el Contexto Gráfico.
points es una lista o tupla de pares de
coordenadas en tuplas, como por ejemplo [ (0,0), (2,5), (3,7), (4,11) ], que representa la lista de de los puntos que se van a conectar con líneas.
drawable.draw_rgb_image(gc,x,y,width,height,dith,rgb_buf,rowstride) # dibuja imagen rgb drawable.draw_rgb_32_image(gc,x,y,width,height,dith,buf,rowstride) # dibuja imagen rgb 32 drawable.draw_gray_image(gc,x,y,width,height,dith,buf,rowstride) # dibuja imagen en escala de grises
gc es el Contexto Gráfico.
x e y son las coordenadas de
la esquina superior izquierda del rectángulo que bordea la imagen.
width y height son el ancho
y el alto del rectángulo que bordea la imagen.
dith es el uno de los métodos de mezclado que se explican a continuación:
Para el método draw_rgb_image() ,
rgb_buf es el conjunto de los datos de la imagen RGB
codificado en una cadena como una secuencia de tripletes de píxeles RGB de 8
bits. Para el método draw_rgb_32_image() ,
buf es el conjunto de los datos de la imagen RGB
codificado en una cadena como una secuencia de tripletes de píxeles RGB de
8 bits con relleno de 8 bits (4 caracteres por cada píxel RGB). Para el método
draw_gray_image() , buf es el conjunto
de datos de la imagen codificado en una cadena como píxeles de 8 bits.
rowstride es el número de caracteres desde
el principio de una fila hasta el principio de la siguiente en la imagen.
rowstride normalmente tiene un valor por defecto de 3 * ancho (width) en el método
draw_rgb_image() ; 4 * ancho (width)para el método draw_rgb_32_image(); y el ancho (width) para el método draw_gray_image() . Si rowstride es 0
entonces la linea se repetirá un número de veces igual al alto.
Los modos de mezclado (dither) son:
RGB_DITHER_NONE # Nunca se hace mezclado RGB_DITHER_NORMAL # Se hace mezclado cuando se usen 8 bits por píxel (o menos) sólamente. RGB_DITHER_MAX # Se hace mezclado cuando se usen 16 bits por píxel o menos.
El programa de ejemplo
drawingarea.py muestra el uso de la mayoría de los
métodos de un área de dibujo (DrawingArea). También inserta el área de dibujo (DrawingArea) en el interior de una ventana con barras de desplazamiento (ScrolledWindow) y añade los controles de desplazamiento horizontal y vertical (Ruler). La figura
Figura 12.1, “Ejemplo de Área de Dibujo” muestra la ventana resultante:
El código fuente de drawingarea.py
está abajo y usa el mapa de píxeles gtk.xpm :
1 #!/usr/bin/env python
2
3 # example 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 DrawingAreaExample:
13 def __init__(self):
14 window = gtk.Window(gtk.WINDOW_TOPLEVEL)
15 window.set_title("Ejemplo de Área de Dibujo")
16 window.connect("destroy", lambda w: gtk.main_quit())
17 self.area = gtk.DrawingArea()
18 self.area.set_size_request(400, 300)
19 self.pangolayout = self.area.create_pango_layout("")
20 self.sw = gtk.ScrolledWindow()
21 self.sw.add_with_viewport(self.area)
22 self.table = gtk.Table(2,2)
23 self.hruler = gtk.HRuler()
24 self.vruler = gtk.VRuler()
25 self.hruler.set_range(0, 400, 0, 400)
26 self.vruler.set_range(0, 300, 0, 300)
27 self.table.attach(self.hruler, 1, 2, 0, 1, yoptions=0)
28 self.table.attach(self.vruler, 0, 1, 1, 2, xoptions=0)
29 self.table.attach(self.sw, 1, 2, 1, 2)
30 window.add(self.table)
31 self.area.set_events(gtk.gdk.POINTER_MOTION_MASK |
32 gtk.gdk.POINTER_MOTION_HINT_MASK )
33 self.area.connect("expose-event", self.area_expose_cb)
34 def motion_notify(ruler, event):
35 return ruler.emit("motion_notify_event", event)
36 self.area.connect_object("motion_notify_event", motion_notify,
37 self.hruler)
38 self.area.connect_object("motion_notify_event", motion_notify,
39 self.vruler)
40 self.hadj = self.sw.get_hadjustment()
41 self.vadj = self.sw.get_vadjustment()
42 def val_cb(adj, ruler, horiz):
43 if horiz:
44 span = self.sw.get_allocation()[3]
45 else:
46 span = self.sw.get_allocation()[2]
47 l,u,p,m = ruler.get_range()
48 v = adj.value
49 ruler.set_range(v, v+span, p, m)
50 while gtk.events_pending():
51 gtk.main_iteration()
52 self.hadj.connect('value-changed', val_cb, self.hruler, True)
53 self.vadj.connect('value-changed', val_cb, self.vruler, False)
54 def size_allocate_cb(wid, allocation):
55 x, y, w, h = allocation
56 l,u,p,m = self.hruler.get_range()
57 m = max(m, w)
58 self.hruler.set_range(l, l+w, p, m)
59 l,u,p,m = self.vruler.get_range()
60 m = max(m, h)
61 self.vruler.set_range(l, l+h, p, m)
62 self.sw.connect('size-allocate', size_allocate_cb)
63 self.area.show()
64 self.hruler.show()
65 self.vruler.show()
66 self.sw.show()
67 self.table.show()
68 window.show()
69
70 def area_expose_cb(self, area, event):
71 self.style = self.area.get_style()
72 self.gc = self.style.fg_gc[gtk.STATE_NORMAL]
73 self.draw_point(10,10)
74 self.draw_points(110, 10)
75 self.draw_line(210, 10)
76 self.draw_lines(310, 10)
77 self.draw_segments(10, 100)
78 self.draw_rectangles(110, 100)
79 self.draw_arcs(210, 100)
80 self.draw_pixmap(310, 100)
81 self.draw_polygon(10, 200)
82 self.draw_rgb_image(110, 200)
83 return gtk.TRUE
84
85 def draw_point(self, x, y):
86 self.area.window.draw_point(self.gc, x+30, y+30)
87 self.pangolayout.set_text("Punto")
88 self.area.window.draw_layout(self.gc, x+5, y+50, self.pangolayout)
89 return
90
91 def draw_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.area.window.draw_points(self.gc, points)
95 self.pangolayout.set_text("Puntos")
96 self.area.window.draw_layout(self.gc, x+5, y+50, self.pangolayout)
97 return
98
99 def draw_line(self, x, y):
100 self.area.window.draw_line(self.gc, x+10, y+10, x+20, y+30)
101 self.pangolayout.set_text("Línea")
102 self.area.window.draw_layout(self.gc, x+5, y+50, self.pangolayout)
103 return
104
105 def draw_lines(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.area.window.draw_lines(self.gc, points)
109 self.pangolayout.set_text("Líneas")
110 self.area.window.draw_layout(self.gc, x+5, y+50, self.pangolayout)
111 return
112
113 def draw_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.area.window.draw_segments(self.gc, segments)
117 self.pangolayout.set_text("Segmentos")
118 self.area.window.draw_layout(self.gc, x+5, y+80, self.pangolayout)
119 return
120
121 def draw_rectangles(self, x, y):
122 self.area.window.draw_rectangle(self.gc, gtk.FALSE, x, y, 80, 70)
123 self.area.window.draw_rectangle(self.gc, gtk.TRUE, x+10, y+10, 20, 20)
124 self.area.window.draw_rectangle(self.gc, gtk.TRUE, x+50, y+10, 20, 20)
125 self.area.window.draw_rectangle(self.gc, gtk.TRUE, x+20, y+50, 40, 10)
126 self.pangolayout.set_text("Rectángulos")
127 self.area.window.draw_layout(self.gc, x+5, y+80, self.pangolayout)
128 return
129
130 def draw_arcs(self, x, y):
131 self.area.window.draw_arc(self.gc, gtk.FALSE, x+10, y, 70, 70,
132 0, 360*64)
133 self.area.window.draw_arc(self.gc, gtk.TRUE, x+30, y+20, 10, 10,
134 0, 360*64)
135 self.area.window.draw_arc(self.gc, gtk.TRUE, x+50, y+20, 10, 10,
136 0, 360*64)
137 self.area.window.draw_arc(self.gc, gtk.TRUE, x+30, y+10, 30, 50,
138 210*64, 120*64)
139 self.pangolayout.set_text("Arcos")
140 self.area.window.draw_layout(self.gc, x+5, y+80, self.pangolayout)
141 return
142
143 def draw_pixmap(self, x, y):
144 pixmap, mask = gtk.gdk.pixmap_create_from_xpm(
145 self.area.window, self.style.bg[gtk.STATE_NORMAL], "gtk.xpm")
146
147 self.area.window.draw_drawable(self.gc, pixmap, 0, 0, x+15, y+25,
148 -1, -1)
149 self.pangolayout.set_text("Mapa de Píxeles")
150 self.area.window.draw_layout(self.gc, x+5, y+80, self.pangolayout)
151 return
152
153 def draw_polygon(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.area.window.draw_polygon(self.gc, gtk.TRUE, points)
157 self.pangolayout.set_text("Polígono")
158 self.area.window.draw_layout(self.gc, x+5, y+80, self.pangolayout)
159 return
160
161 def draw_rgb_image(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.area.window.draw_rgb_image(self.gc, x, y, 80, 80,
170 gtk.gdk.RGB_DITHER_NONE, buff, 80*3)
171 self.pangolayout.set_text("Imagen RGB")
172 self.area.window.draw_layout(self.gc, x+5, y+80, self.pangolayout)
173 return
174
175 def main():
176 gtk.main()
177 return 0
178
179 if __name__ == "__main__":
180 DrawingAreaExample()
181 main()