There are a general set of methods that can be used to draw onto
the drawing area 'canvas'. These drawing methods can be used for any
gtk.gdk.Drawable subclass (either a
gtk.gdk.Window or a
gtk.gdk.Pixmap). The drawing methods are:
drawable.draw_point(gc,x,y)
gc is the Graphics Context to be used to do
the drawing.
x and y are the
coordinates of the point.
drawable.draw_line(gc,x1,y1,x2,y2)
gc is the Graphics Context.
x1 and y1 specify
the starting point of the line. x2 and
y2 specify the ending point of the line.
drawable.draw_rectangle(gc,filled,x,y,width,height)
where gc is the Graphics Context.
filled is a boolean indicating the
rectangle should be filled with the foreground color if
TRUE or not filled, if FALSE.
x and y are the top
left corner of the rectangle.
width and
height are the width and height of the
rectangle.
drawable.draw_arc(gc,filled,x,y,width,height,angle1,angle2)
gc is the Graphics Context.
filled is a boolean indicating the arc
should be filled with the foreground color if TRUE or not
filled, if FALSE.
x and y are the top
left corner of the bounding rectangle. width and
height are the width and height of the bounding
rectangle.
angle1 is the start angle of the arc,
relative to the 3 o'clock position, counter-clockwise, in 1/64ths of a
degree.
angle2 is the end angle of the arc,
relative to angle1, in 1/64ths of a degree counter
clockwise.
drawable.draw_polygon(gc,filled,points)
gc is the Graphics Context.
filled is a boolean indicating the polygon
should be filled with the foreground color if TRUE or not filled, if FALSE.
points is a list of coordinate pairs in
tuples e.g. [ (0,0), (2,5), (3,7), (4,11) ] of the points to be drawn as a
connected polygon.
drawable.draw_string(font,gc,x,y,string) drawable.draw_text(font,gc,x,y,string)
font is the
gtk.gdk.Font to use to render the string.
gc is the Graphics Context.
x and y are the
coordinates of the point to start rendering the string i.e the left
baseline.
string is the string of characters to
render.
Both the draw_string() and
draw_text() methods are deprecated - use a
pango.Layout instead with the
draw_layout() method.
drawable.draw_layout(gc,x,y,layout)
gc is the Graphics Context.
x and y are the
coordinates of the point to start rendering the layout.
layout is the
pango.Layout that is to be rendered.
drawable.draw_drawable(gc,src,xsrc,ysrc,xdest,ydest,width,height)
gc is the Graphics Context.
src is the source drawable.
xsrc and ysrc are the
coordinates of the top left rectangle in the source drawable.
xdest and ydest are the
coordinates of the top left corner in the drawing area.
width and height are
the width and height of the source drawable area to be copied to the
drawable. If width or
height is -1 then the full width or height of the
drawable is used.
drawable.draw_image(gc,image,xsrc,ysrc,xdest,ydest,width,height)
gc is the Graphics Context.
image is the source image.
xsrc and ysrc are the
coordinates of the top left rectangle in the source drawable.
xdest and ydest are the
coordinates of the top left corner in the drawing area.
width and height are
the width and height of the source drawable area to be copied to the
drawable. If width or
height is -1 then the full width or height of the
image is used.
drawable.draw_points(gc,points)
gc is the Graphics Context.
points is a list or tuple of coordinate
pairs in tuples e.g. [ (0,0), (2,5), (3,7), (4,11) ] of the points to be
drawn.
drawable.draw_segments(gc,segs)
gc is the Graphics Context.
segs is a list or tuple of start and end
coordinate pairs in tuples e.g. [ (0,0, 1,5), (2,5, 1,7), (3,7, 1,11),
(4,11, 1,13) ] of the line segments to be drawn.
drawable.draw_lines(gc,points)
gc is the Graphics Context.
points is a list or tuple of coordinate
pairs in tuples e.g. [ (0,0), (2,5), (3,7), (4,11) ] of the points to be
connected with lines.
drawable.draw_rgb_image(gc,x,y,width,height,dith,rgb_buf,rowstride) drawable.draw_rgb_32_image(gc,x,y,width,height,dith,buf,rowstride) drawable.draw_gray_image(gc,x,y,width,height,dith,buf,rowstride)
gc is the Graphics Context.
x and y are the top
left corner of the image bounding rectangle.
width and height are
the width and height of the image bounding rectangle.
dith is the dither mode as described
below
For the draw_rgb_image() method,
rgb_buf is the RGB Image data packed in a string as a
sequence of 8-bit RGB pixel triplets. For the
draw_rgb_32_image() method,
buf is the RGB Image data packed in a string as a
sequence of 8-bit RGB pixel triplets with 8-bit padding (4 characters per
RGB pixel). For the draw_gray_image() method,
buf is the gray image data packed in a string as
8-bit pixel data.
rowstride is the number of characters from
the start of one row to the start of the next row of the image.
rowstride usually defaults to: 3 *
width for the
draw_rgb_image() method; 4 *
width for the
draw_rgb_32_image(); and,
width for the
draw_gray_image() method. If
rowstride is 0 the line will be replicated
height times.
The dither modes are:
RGB_DITHER_NONE # Never use dithering. RGB_DITHER_NORMAL # Use dithering in 8 bits per pixel (and below) only. RGB_DITHER_MAX # Use dithering in 16 bits per pixel and below.
The drawingarea.py
example program demonstrates the use of most of the
DrawingArea methods. It also puts the
DrawingArea inside a
ScrolledWindow and adds horizontal and vertical
Ruler widgets. Figure 12.1, “Drawing Area Example” shows
the program in operation:
The drawingarea.py
source code is below and uses the gtk.xpm pixmap:
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("Drawing Area Example")
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 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("Point")
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("Points")
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("Line")
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("Lines")
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("Segments")
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, False, x, y, 80, 70)
123 self.area.window.draw_rectangle(self.gc, True, x+10, y+10, 20, 20)
124 self.area.window.draw_rectangle(self.gc, True, x+50, y+10, 20, 20)
125 self.area.window.draw_rectangle(self.gc, True, x+20, y+50, 40, 10)
126 self.pangolayout.set_text("Rectangles")
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, False, x+10, y, 70, 70,
132 0, 360*64)
133 self.area.window.draw_arc(self.gc, True, x+30, y+20, 10, 10,
134 0, 360*64)
135 self.area.window.draw_arc(self.gc, True, x+50, y+20, 10, 10,
136 0, 360*64)
137 self.area.window.draw_arc(self.gc, True, x+30, y+10, 30, 50,
138 210*64, 120*64)
139 self.pangolayout.set_text("Arcs")
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("Pixmap")
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, True, points)
157 self.pangolayout.set_text("Polygon")
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("RGB Image")
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()