12.2. Métodos de Dibujo

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.

Nota

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:

Figura 12.1. Ejemplo de Área de Dibujo

Ejemplo de Área de Dibujo

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()