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 python3
2"""
3Based on cairo-demo/X11/cairo-demo.c
4"""
5
6import cairo
7import gi
8
9gi.require_version('Gtk', '4.0')
10from gi.repository import Gtk
11
12SIZE = 30
13
14
15class Application(Gtk.Application):
16
17 def do_activate(self):
18 window = Gtk.ApplicationWindow(application=self, default_width=450, default_height=600)
19
20 drawing_area = Gtk.DrawingArea()
21 drawing_area.set_draw_func(self.draw)
22 window.set_child(drawing_area)
23
24 window.present()
25
26 def triangle(self, ctx):
27 ctx.move_to(SIZE, 0)
28 ctx.rel_line_to(SIZE, 2 * SIZE)
29 ctx.rel_line_to(-2 * SIZE, 0)
30 ctx.close_path()
31
32 def square(self, ctx):
33 ctx.move_to(0, 0)
34 ctx.rel_line_to(2 * SIZE, 0)
35 ctx.rel_line_to(0, 2 * SIZE)
36 ctx.rel_line_to(-2 * SIZE, 0)
37 ctx.close_path()
38
39 def bowtie(self, ctx):
40 ctx.move_to(0, 0)
41 ctx.rel_line_to(2 * SIZE, 2 * SIZE)
42 ctx.rel_line_to(-2 * SIZE, 0)
43 ctx.rel_line_to(2 * SIZE, -2 * SIZE)
44 ctx.close_path()
45
46 def inf(self, ctx):
47 ctx.move_to(0, SIZE)
48 ctx.rel_curve_to(0, SIZE, SIZE, SIZE, 2 * SIZE, 0)
49 ctx.rel_curve_to(SIZE, -SIZE, 2 * SIZE, -SIZE, 2 * SIZE, 0)
50 ctx.rel_curve_to(0, SIZE, -SIZE, SIZE, - 2 * SIZE, 0)
51 ctx.rel_curve_to(-SIZE, -SIZE, - 2 * SIZE, -SIZE, - 2 * SIZE, 0)
52 ctx.close_path()
53
54 def draw_shapes(self, ctx, x, y, fill):
55 ctx.save()
56
57 ctx.new_path()
58 ctx.translate(x + SIZE, y + SIZE)
59 self.bowtie(ctx)
60 if fill:
61 ctx.fill()
62 else:
63 ctx.stroke()
64
65 ctx.new_path()
66 ctx.translate(3 * SIZE, 0)
67 self.square(ctx)
68 if fill:
69 ctx.fill()
70 else:
71 ctx.stroke()
72
73 ctx.new_path()
74 ctx.translate(3 * SIZE, 0)
75 self.triangle(ctx)
76 if fill:
77 ctx.fill()
78 else:
79 ctx.stroke()
80
81 ctx.new_path()
82 ctx.translate(3 * SIZE, 0)
83 self.inf(ctx)
84 if fill:
85 ctx.fill()
86 else:
87 ctx.stroke()
88
89 ctx.restore()
90
91 def fill_shapes(self, ctx, x, y):
92 self.draw_shapes(ctx, x, y, True)
93
94 def stroke_shapes(self, ctx, x, y):
95 self.draw_shapes(ctx, x, y, False)
96
97 def draw(self, da, ctx, width, height):
98 ctx.set_source_rgb(0, 0, 0)
99
100 ctx.set_line_width(SIZE / 4)
101 ctx.set_tolerance(0.1)
102
103 ctx.set_line_join(cairo.LINE_JOIN_ROUND)
104 ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0)
105 self.stroke_shapes(ctx, 0, 0)
106
107 ctx.set_dash([], 0)
108 self.stroke_shapes(ctx, 0, 3 * SIZE)
109
110 ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
111 self.stroke_shapes(ctx, 0, 6 * SIZE)
112
113 ctx.set_line_join(cairo.LINE_JOIN_MITER)
114 self.stroke_shapes(ctx, 0, 9 * SIZE)
115
116 self.fill_shapes(ctx, 0, 12 * SIZE)
117
118 ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
119 self.fill_shapes(ctx, 0, 15 * SIZE)
120 ctx.set_source_rgb(1, 0, 0)
121 self.stroke_shapes(ctx, 0, 15 * SIZE)
122
123
124app = Application()
125app.run()