I have taken passing shots at learning Cairo in the past, but always moved on in favor of some other graphics library. My problem is that I can't find a good tutorial that gives me a simple display for my surface. I have always ended up digging through GTK or QT documentation about things that have nothing to do with what I want to do. I want to learn Cairo, not a massive OO architecture.
What is a bare bones wrapper to give me a cross-platform window with a Cairo canvas to draw on?
I have used cairo for virtually anything involving drawing. I work at a medical software company, so I prototype scientific data visualization and other things.
I have usually three ways to display my drawings:
- A GTK drawing area created with a Python script and GTK;
- A PNG image displayed directly on screen using Python Image Library
show()
method;
- A PNG image saved to disk, also via Python Image Library.
A simple script derived from cairographics examples, which actually I use as a template for any new project, is:
import gtk
class Canvas(gtk.DrawingArea):
def __init__(self):
super(Canvas, self).__init__()
self.connect("expose_event", self.expose)
self.set_size_request(800,500)
def expose(self, widget, event):
cr = widget.window.cairo_create()
rect = self.get_allocation()
# you can use w and h to calculate relative positions which
# also change dynamically if window gets resized
w = rect.width
h = rect.height
# here is the part where you actually draw
cr.move_to(0,0)
cr.line_to(w/2, h/2)
cr.stroke()
window = gtk.Window()
canvas = Canvas()
window.add(canvas)
window.set_position(gtk.WIN_POS_CENTER)
window.show_all()
gtk.main()
Or if you prefer not to deal with GUI toolkits, you can create and display an image on screen, and optionally save it to file:
import cairo, Image
width = 800
height = 600
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
cr = cairo.Context(surface)
# optional conversion from screen to cartesian coordinates:
cr.translate(0, height)
cr.scale(1, -1)
# something very similar to Japanese flag:
cr.set_source_rgb(1,1,1)
cr.rectangle(0, 0, width, height)
cr.fill()
cr.arc(width/2, height/2, 150, 0, 6.28)
cr.set_source_rgb(1,0,0)
cr.fill()
im = Image.frombuffer("RGBA",
(width, height),
surface.get_data(),
"raw",
"BGRA",
0,1) # don't ask me what these are!
im.show()
# im.save('filename', 'png')
An answer to a related question demonstrates a very simple setup in Gtk2HS to draw on a drawingArea with Cairo.
import Graphics.UI.Gtk
import Graphics.Rendering.Cairo
main :: IO ()
main = do
initGUI
window <- windowNew
drawingArea <- drawingAreaNew
containerAdd window drawingArea
drawingArea `onExpose` (\_ -> renderScene drawingArea)
window `onDestroy` mainQuit
windowSetDefaultSize window 640 480
widgetShowAll window
mainGUI
renderScene :: DrawingArea -> IO Bool
renderScene da = do
dw <- widgetGetDrawWindow da
renderWithDrawable dw $ do setSourceRGBA 0.5 0.5 0.5 1.0
moveTo 100.0 100.0
showText "HelloWorld"
return True
Simply pass your Cairo animation routine to renderWithDrawable dw
in renderScene
.