Cairo Integration
Despite cairo not being a GObject based library, PyGObject provides special cairo integration through pycairo. Functions returning and taking cairo data types get automatically converted to pycairo objects and vice versa.
Some distros ship the PyGObject cairo support in a separate package. If you’ve followed the instructions on “Getting Started” you should have everything installed.
If your application requires the cairo integration you can use
gi.require_foreign()
:
try:
gi.require_foreign("cairo")
except ImportError:
print("No pycairo integration :(")
Note that PyGObject currently does not support cairocffi, only pycairo.
Demo
The following example shows a Gtk.Window
with a custom drawing in Python
using pycairo.

1#!/usr/bin/env python
2"""
3Based on cairo-demo/X11/cairo-demo.c
4"""
5
6import cairo
7import gi
8gi.require_version("Gtk", "3.0")
9from gi.repository import Gtk
10
11SIZE = 30
12
13
14def triangle(ctx):
15 ctx.move_to(SIZE, 0)
16 ctx.rel_line_to(SIZE, 2 * SIZE)
17 ctx.rel_line_to(-2 * SIZE, 0)
18 ctx.close_path()
19
20
21def square(ctx):
22 ctx.move_to(0, 0)
23 ctx.rel_line_to(2 * SIZE, 0)
24 ctx.rel_line_to(0, 2 * SIZE)
25 ctx.rel_line_to(-2 * SIZE, 0)
26 ctx.close_path()
27
28
29def bowtie(ctx):
30 ctx.move_to(0, 0)
31 ctx.rel_line_to(2 * SIZE, 2 * SIZE)
32 ctx.rel_line_to(-2 * SIZE, 0)
33 ctx.rel_line_to(2 * SIZE, -2 * SIZE)
34 ctx.close_path()
35
36
37def inf(ctx):
38 ctx.move_to(0, SIZE)
39 ctx.rel_curve_to(0, SIZE, SIZE, SIZE, 2 * SIZE, 0)
40 ctx.rel_curve_to(SIZE, -SIZE, 2 * SIZE, -SIZE, 2 * SIZE, 0)
41 ctx.rel_curve_to(0, SIZE, -SIZE, SIZE, - 2 * SIZE, 0)
42 ctx.rel_curve_to(-SIZE, -SIZE, - 2 * SIZE, -SIZE, - 2 * SIZE, 0)
43 ctx.close_path()
44
45
46def draw_shapes(ctx, x, y, fill):
47 ctx.save()
48
49 ctx.new_path()
50 ctx.translate(x + SIZE, y + SIZE)
51 bowtie(ctx)
52 if fill:
53 ctx.fill()
54 else:
55 ctx.stroke()
56
57 ctx.new_path()
58 ctx.translate(3 * SIZE, 0)
59 square(ctx)
60 if fill:
61 ctx.fill()
62 else:
63 ctx.stroke()
64
65 ctx.new_path()
66 ctx.translate(3 * SIZE, 0)
67 triangle(ctx)
68 if fill:
69 ctx.fill()
70 else:
71 ctx.stroke()
72
73 ctx.new_path()
74 ctx.translate(3 * SIZE, 0)
75 inf(ctx)
76 if fill:
77 ctx.fill()
78 else:
79 ctx.stroke()
80
81 ctx.restore()
82
83
84def fill_shapes(ctx, x, y):
85 draw_shapes(ctx, x, y, True)
86
87
88def stroke_shapes(ctx, x, y):
89 draw_shapes(ctx, x, y, False)
90
91
92def draw(da, ctx):
93 ctx.set_source_rgb(0, 0, 0)
94
95 ctx.set_line_width(SIZE / 4)
96 ctx.set_tolerance(0.1)
97
98 ctx.set_line_join(cairo.LINE_JOIN_ROUND)
99 ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0)
100 stroke_shapes(ctx, 0, 0)
101
102 ctx.set_dash([], 0)
103 stroke_shapes(ctx, 0, 3 * SIZE)
104
105 ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
106 stroke_shapes(ctx, 0, 6 * SIZE)
107
108 ctx.set_line_join(cairo.LINE_JOIN_MITER)
109 stroke_shapes(ctx, 0, 9 * SIZE)
110
111 fill_shapes(ctx, 0, 12 * SIZE)
112
113 ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
114 fill_shapes(ctx, 0, 15 * SIZE)
115 ctx.set_source_rgb(1, 0, 0)
116 stroke_shapes(ctx, 0, 15 * SIZE)
117
118
119def main():
120 win = Gtk.Window()
121 win.connect('destroy', lambda w: Gtk.main_quit())
122 win.set_default_size(450, 550)
123
124 drawingarea = Gtk.DrawingArea()
125 win.add(drawingarea)
126 drawingarea.connect('draw', draw)
127
128 win.show_all()
129 Gtk.main()
130
131
132if __name__ == '__main__':
133 main()