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