CairoUI
Revision 2 as of 2010-03-03 18:54:04
Clear message
Ubuntu Opportunistic Developers Week March 2010 - Creating stunning interfaces with Cairo - Laszlo Pandy - Mar 3 2010
(12:01:55 PM) laszlok: Hello everyone, i'm gonna be talking about using cairo with python today (12:02:30 PM) laszlok: I haven't prepared any slides, but I'll be using some links (12:02:57 PM) laszlok: and it will be less structured than usual, so feel free to shout out or ask questions at any time in #ubuntu-classroom-chat (12:03:20 PM) laszlok: I won't mind taking a large detour, we'll probably have plenty of time for it (12:03:52 PM) laszlok: So cairo is a drawing API (12:04:05 PM) laszlok: if you know about SVG graphics, it does the same sort of thing (12:04:27 PM) laszlok: it has strokes, fills, gradients, etc (12:04:49 PM) laszlok: Its also a very modern drawing api (12:04:55 PM) laszlok: the library was written quite recently (12:05:34 PM) laszlok: I mean modern in that it has good alpha support, and really good antialiasing (12:05:46 PM) laszlok: so when you draw graphics they scale well and look very clean (12:06:17 PM) laszlok: unlike previous generation APIs like Java graphics (don't get me started) (12:07:07 PM) laszlok: Cairo integrates really well with GTK, in fact most widgets in GTK are now drawn using cairo (12:07:42 PM) laszlok: I will show you how to use it with GTK and also how to use some other cairo backends like svg, pdf, and png (12:08:26 PM) laszlok: In terms of creating stunning interfaces, it can be done with cairo. If you create a stunning GTK app then you are doing it with cairo anyway ;) (12:08:42 PM) laszlok: however cairo is low level (12:09:15 PM) laszlok: if you are using cairo directly you are drawing all the lines and calculating all the geometry yourself (12:10:09 PM) laszlok: There was a talk yesterday about goocanvas, which uses cairo and gives a much higher level view. You can deal with objects instead of geometry calculations. (12:10:36 PM) laszlok: But if anyone has questions about that, please ask (12:10:55 PM) laszlok: http://www.cairographics.org/samples/ (12:11:29 PM) laszlok: here is a page on the cairo website with some sample code and how it will look (12:11:45 PM) laszlok: the code is in C, but it is quite similar to python as you will see (12:12:55 PM) laszlok: QUESTION: Can we build all the application interface using Cairo (except for the Window container)? (12:13:59 PM) laszlok: yes you can, but it will involve a lot of trickiness if you want to detect mouse clicks on many different objects (12:14:37 PM) laszlok: it will work fine for a simple drawing, but once you start using lots of objects you might find the geometry to figure out which one is clicked it too much (12:14:53 PM) laszlok: this is why things like goocanvas were invented; to automate those things (12:15:39 PM) laszlok: QUESTION: can we use cairo to create the interface separate from the logic that runs the program? (12:15:58 PM) laszlok: yes, in the same way that you would have a GTK interface separate from the program logic (12:16:20 PM) laszlok: QUESTION: maybe for later, is there a preferred way of doing animations in cairo? (12:16:53 PM) laszlok: cairo does not provide support for animations, so it has to be done essentially the same as animations in other drawing apis (12:17:36 PM) laszlok: that means having a timer to redraw the screen and have code to redraw the whole screen (or just the parts that change) (12:18:24 PM) laszlok: so as you can see in the samples, cairo has primitives for arcs, lines, etc. (12:18:45 PM) laszlok: Thinking about an interface in these primitives is a bit low level, but it gives you the great flexibility (12:19:07 PM) laszlok: QUESTION: Does the animation redraw method you just described use a lot of cpu power? (12:19:23 PM) laszlok: if your drawing is complex, it probably will (12:19:51 PM) laszlok: but cairo is quite efficient, and allows you flexibility for caching drawings (12:20:27 PM) laszlok: for example if you have a background which requires a long time to draw, you can draw it to an ImageSurface in memory instead (12:20:39 PM) laszlok: and then it is one operation to draw it on screen (12:21:20 PM) laszlok: QUESTION: would like to add to performance that strokes are the ones that are expensive. (12:21:37 PM) laszlok: that's not a question ;) (12:22:09 PM) laszlok: http://www.cairographics.org/documentation/pycairo/reference/index.html (12:22:35 PM) laszlok: here is the python documentation for cairo (12:22:49 PM) laszlok: that is good reference when looking at the next link (12:23:03 PM) laszlok: http://laszlopandy.com/files/drawing_interface.html (12:23:19 PM) laszlok: here is some poorly commented python code I prepared (12:23:29 PM) laszlok: QUESTION: waht are all the required components to start working on cairo+python? (12:23:36 PM) laszlok: only cairo, python and pycairo (12:24:03 PM) laszlok: if you want to render directly on screen (as opposed to png or svg) you should have pygtk installed as well (12:24:45 PM) laszlok: for example, in the code i prepared I am importing both gtk and cairo (12:25:03 PM) laszlok: copy and paste this code into your editor (12:25:14 PM) laszlok: if you run it with no arguments you will get a gtk window (12:25:41 PM) laszlok: if you give it 'png', 'svg' or 'pdf' as an argument, it will generate that kind of file (12:25:59 PM) laszlok: so lets take a look at the GTK code, in the DrawingInterface class (12:26:50 PM) laszlok: it creates a window, and adds a gtk.DrawingArea (12:27:14 PM) laszlok: the DrawingArea is a widget which is like a blank canvas we can draw to (12:28:00 PM) laszlok: then we set the size of the window, and show it (12:28:07 PM) laszlok: not much to see there (12:28:33 PM) laszlok: the expose event is the event when the X server tells the window to redraw itself (12:28:47 PM) laszlok: so this is what we are using to trigger our drawing code (12:29:27 PM) laszlok: also notice that in the GTK code the cairo context is created directy from the widget. GTK is integrated with cairo and makes it easy (12:29:54 PM) laszlok: the context is what holds all the information about your drawing as you add lines and shapes (12:30:31 PM) laszlok: the draw_rounded_rentangle() method is converted from the C example on http://www.cairographics.org/samples/ (12:30:47 PM) laszlok: if you compare them you can see it is mostly identical code (12:31:08 PM) laszlok: QUESTION: please explain the underlying functiosn used in on_expose (12:31:23 PM) laszlok: http://laszlopandy.com/files/drawing_interface.html (12:31:51 PM) laszlok: in on_expose we create the cairo context associated with the widget (12:32:01 PM) laszlok: so when we draw using that context, it will draw on the widget (12:32:30 PM) laszlok: widget.get_allocation() returns a renctangle with the width and height of the window, so we know how much space we have to draw (12:32:50 PM) laszlok: and self.drawing.draw() calls the method on the drawing class three lines below that (12:33:10 PM) laszlok: QUESTION: will the get_allocation be called only after drawing.draw is called? (12:33:16 PM) laszlok: this is equivalent to: (12:33:25 PM) laszlok: rectangle = widget.get_allocation() (12:33:34 PM) laszlok: self.drawing.draw(ctx, rectangle) (12:34:13 PM) laszlok: so the draw() method can know the size of the widget (12:34:48 PM) laszlok: by default, the DrawingArea widget is the default gtk colour (12:35:08 PM) laszlok: so in the draw() method I create a rectangle the size of the widget and fill it with white (12:35:34 PM) laszlok: the context remembers things like rectangles i have created, and also what colour i set it (12:36:00 PM) laszlok: after I call fill() the rectangle is removed from the context and put on the screen, but the colour is still set (12:36:14 PM) laszlok: so remember to change your colour or it will be whatever you set it previously (12:36:28 PM) laszlok: QUESTION: Is it possible to do some basic 3d transformation? (Like perspective on GIMP) (12:36:38 PM) laszlok: cairo is a 2d canvas, but you can do transformation (12:36:52 PM) laszlok: to fake a perspective (12:37:20 PM) laszlok: take a look at http://www.cairographics.org/documentation/pycairo/reference/matrix.html#class-matrix (12:38:04 PM) laszlok: In get_gradient() http://laszlopandy.com/files/drawing_interface.html (12:38:15 PM) laszlok: you can see cairo makes gradients really simple (12:38:56 PM) laszlok: you create a gradient with a start and end point to define how long the colour change will be and in what direction (12:39:14 PM) laszlok: and then you set stops on the gradient, just like you would do on inkscape or other graphics programs (12:39:36 PM) laszlok: the first argument to add_color_stop_rgb is the offset between 0 and 1 (12:39:51 PM) laszlok: so i set two colour stops. One at the beginning and one at the end (12:40:21 PM) laszlok: you can easily add a third one in set it to offset 0.5 and your gradient will blend three colours (12:41:09 PM) laszlok: now look at the bottom part of the code where it says if arg == 'pdf': (12:41:40 PM) laszlok: i mentioned earlier about using image surfaces to store your drawing in memory (12:41:58 PM) laszlok: surfaces also allow you do store in files (12:42:07 PM) laszlok: QUESTION: can you set the gradient to go through the hues in the opposite direction? (12:42:09 PM) laszlok: yes (12:42:15 PM) laszlok: either reverse the offsets (12:42:27 PM) laszlok: (set the first one to offset 1, and second to offset 0) (12:43:34 PM) laszlok: or reverse the pairs of (x,y) parameters to the LinearGradient constructor (12:44:08 PM) laszlok: QUESTION: does the context variable acts as a placeholder or as a memory buffer? (12:44:30 PM) laszlok: it is the same as the drawing context created from the GTK widget except it writes to a file (12:45:10 PM) laszlok: so it will store your drawing in memory and write it to the file when you complete a fill() or stroke() (12:45:25 PM) laszlok: QUESTION: How to make it write to a jpg file? (12:46:05 PM) laszlok: JPG file compression is meant for pictures where there are not perfectly smooth lines (12:46:30 PM) laszlok: PNG compression works much better for drawings, things with smooth and sharp borders (12:46:58 PM) laszlok: so cairo does not support JPG directly, i would write to svg or png and use imagemagick to convert it (12:48:41 PM) laszlok: so as you can see, cairo surfaces make it really easy to export to other formats (12:49:09 PM) laszlok: and if you were writing on windows or mac, you would use a surface specifically for the platform and the rest of the api would be the same (12:50:14 PM) laszlok: any questions? (12:50:47 PM) laszlok: QUESTION: does cairo do that "redraw only changed parts" automagically, or do we manually tell what changed ? (12:50:52 PM) laszlok: you could have to do that manually (12:51:08 PM) laszlok: in this case i redraw the white rectangle each time, therefore blanking the entire screen (12:51:25 PM) laszlok: this is something that goocanvas would also automate for you (12:52:26 PM) laszlok: QUESTION: How difficult is it to use cairo in combination with pygoocanvas? (For example, if I wanted to draw/animate something like a progress indicator on top of my goocanvas while waiting for goocanvas to update during a slow operation.) (12:52:47 PM) laszlok: that seems like a strange use case, but it should work (12:52:57 PM) laszlok: theoretically you can use cairo to draw on top of any GTK widget (12:53:04 PM) laszlok: as long as the proper flags are set (12:55:03 PM) laszlok: QUESTION: What are the advantages of using cairo directly instead of through goocanvas? (12:55:27 PM) laszlok: goocanvas is much higher level (12:55:36 PM) laszlok: and cairo is very lightweight (12:56:05 PM) laszlok: if you are doing something simple and want the flexibility, or don't mind doing the drawing manually then cairo is the way to go (12:56:40 PM) laszlok: its really easy to get started with, and can work with GTK mouse clicks, etc well for simpler things (12:57:08 PM) laszlok: if you know you have a bunch of objects you want to drag around on the screen, goocanvas will probably make your life much easier (12:57:55 PM) laszlok: QUESTION: the png format uses the format_argb32 constant. the manual shows 3 more. can u tell the formats they specify? (12:58:18 PM) laszlok: referring to http://www.cairographics.org/documentation/pycairo/reference/constants.html#constants-format (12:58:50 PM) laszlok: FORMAT_ARGB32 is colour surface with alpha support (12:59:10 PM) laszlok: FORMAT_RGB24 is the same without alpha support so you will not be able to do transparency (12:59:40 PM) laszlok: the others are for alpha only masks and do not store colour values (01:00:20 PM) laszlok: these formats are for image surfaces. You may need to specify alpha only if you want to make a transparency mask