For my own benefit and possibly for educational use, I would like to make a pygame-like API for Python and Cairo. But I don't want it to be exactly pygame. I would instead like to make it a semi-static drawing platform that display one or more images using GTK/GDK, and I would like to imitate the excellent API principles of TiKZ (the latex package). The PyGame API is not bad, but I'm not satisfied with it. One particular issue is that I would like the package to handle window refresh by drawing everything into a pixbuf (with Cairo), and automatically redraw the pixbuf when the window is uncovered. That way the end programmer doesn't have to worry about window refresh. In fact, the end programmer shouldn't have to write a single class or function or any more than a straight sequence of lines of code to draw a smiley face (say). The graphics library also doesn't have to maintain an ever-longer list of stored shape objects as is the case in TkInter. (At least, I hope that Cairo doesn't do that against my intentions.)

I succeeded in drawing various things in pycairo with output to ImageMagick and Postscript. So I'm okay with pycairo itself.

Unfortunately, the cairo/gtk/pycairo/pygtk documentation that I found --- I don't know who it's written for, but not for me. At the moment, I am a Project Euler type of programmer, not a "5 bleeding edge ultra-object-oriented APIs" type of programmer. I'd like to see a clear explanation of what to do, and/or a clear example.


Okay, I accepted the one answer that was posted because it was at least a little helpful. But here in a nutshell is the real point. The point is that GDK make a temporary double buffer when you draw things in GDK, including using Cairo. It is expected that when you handle an expose event, you will just redraw everything. But if you have a very complicated image, this is a slow process, especially in Python. So it would be much nicer if Cairo could write to a permanent double buffer rather than a temporary one, and then that permanent double buffer would be exposed with GDK. Several developers have wanted a solution to this problem. One of the projects that seems to have some kind of solution is Google Chromium --- have you ever noticed how great window exposure is in Google Chrome, for instance in Linux? So I will look at the Chromium source code to see if I can do this easily.

Addendum: I see that I did confuse the issue by referring specifically to "pixbufs". I don't really care about pixbufs (and I changed the question title again). What I really care about is creating a permanent double buffer pixel array between Cairo and GTK/GDK, instead of a temporary double buffer pixel array. It seems that the easiest way to do that is to make the GTK window a Cairo surface and make the double buffer another Cairo surface. Since I asked for an sample in my question, here is some:

class Canvas(gtk.DrawingArea):
    def __init__(self):
        super(Canvas, self).__init__()
        self.connect("expose_event", self.expose)
        self.set_size_request(width,height)

    def expose(self, widget, event):
        cr = widget.window.cairo_create()
        cr.set_source_surface(mybuffer,0,0)
        cr.paint()

Another tricky issue that quickly arose is that I wanted this to be a WYSISWYG drawing environment that immediately draws what Python asks it to draw --- and that can be extended to animations. However, most GTK examples aren't set up that way: event handling is postponed until I either call gtk.main(). (Or in Python, I was surprised to discover that raw_input() also somehow flushes the GTK event queue.) I found a nice explanation, with Python examples, of alternatives to giving away event control to GTK. The simplest solution and possibly the one that I will adopt is to use this to flush the event buffer whenever you want to do that:

while gtk.events_pending(): gtk.main_iteration(False)

There is one final thing that I will need, to flush the pixel buffer as well as the event buffer. It looks like one way to do that is window.queue_draw()

有帮助吗?

解决方案

As this was too big for a comment I have added this as a response.
The question is not quite clear. Do you mean to ask how to use cairo drawing to draw onto Gtk Widgets? Firstly, there is nothing called GTK Pixbuf, I think you are referring to GDK Pixbuf. Most the drawing stuff in GTK is done at GDK layer. If you want to find out about windowing, drawing mechanism or image manipulation you should look into GDK for more details. These links will hopefully help you get some insight about cairo-gdk interaction. Although my experience with python bindings for GTK, GDK & Cairo is nil, but I think that Google will provide you with some good resources if you look up gdk-cairo sample.
Hope this helps at least a bit!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top