Python + Cairo + GTK/GDK像素缓冲区的简单设置



为了我自己的利益和可能的教育用途,我想为Python和Cairo制作一个类似pygame的API。但我不希望它完全是pygame。相反,我想让它成为一个使用GTK/GDK显示一个或多个图像的半静态绘图平台,并且我想模仿TiKZ(乳胶包)的优秀API原则。PyGame API不错,但我对它并不满意。一个特殊的问题是,我希望这个包能够通过将所有内容绘制到像素图中(使用Cairo)来处理窗口刷新,并在窗口未打开时自动重新绘制像素图。这样,最终程序员就不必担心窗口刷新。事实上,最终程序员不需要编写单个类或函数,也不需要编写更多的直接代码序列来绘制笑脸(比如)。图形库也不需要像TkInter那样维护一个越来越长的存储形状对象列表。(至少,我希望开罗不会违背我的意愿。)

我成功地在pycairo中绘制了各种东西,并输出到ImageMagick和Postscript。所以我对pycairo本身没有意见。

不幸的是,我发现cairo/gtk/pycairo/pygtk文档——我不知道它是为谁写的,但不是为我写的。目前,我是Project Euler类型的程序员,而不是"5个前沿的超面向对象api"类型的程序员。我想看到一个清楚的解释,做什么,和/或一个明确的例子。


好吧,我接受了发布的一个答案,因为它至少有点帮助。但简单地说,这才是真正的要点。关键在于,当您在GDK中绘制内容时,包括使用Cairo时,GDK会创建一个临时双缓冲区。当您处理一个暴露事件时,您需要重新绘制所有内容。但是如果你有一个非常复杂的图像,这是一个缓慢的过程,特别是在Python中。因此,如果Cairo能够写入一个永久性双缓冲区而不是一个临时的,那就好得多了,然后这个永久性双缓冲区将在GDK中公开。一些开发人员想要解决这个问题。其中一个似乎有某种解决方案的项目是Google Chromium——你是否注意到Google Chrome的窗口曝光有多好,例如在Linux中?因此,我将查看Chromium源代码,看看我是否可以轻松地做到这一点。

附录:我发现我特别提到"pixbufs"确实混淆了这个问题。我真的不关心pixbufs(我又改了题目)。我真正关心的是在Cairo和GTK/GDK之间创建一个永久的双缓冲像素数组,而不是一个临时的双缓冲像素数组。似乎最简单的方法是将GTK窗口作为Cairo表面,并将双缓冲区作为另一个Cairo表面。既然我在我的问题中要求了一个样本,这里是一些:

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()

另一个迅速出现的棘手问题是,我希望这是一个wyysiswyg绘图环境,可以立即绘制Python要求它绘制的内容-并且可以扩展到动画。然而,大多数GTK示例并不是这样设置的:事件处理被推迟,直到我调用gtk.main()。(或者在Python中,我惊讶地发现raw_input()也以某种方式刷新GTK事件队列。)我找到了一个很好的解释,用Python示例说明了将事件控制交给GTK的替代方法。最简单的解决方案,也可能是我将采用的解决方案,是在需要时使用这个来刷新事件缓冲区:

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

还有最后一件事,我将需要刷新像素缓冲区以及事件缓冲区。一种方法是window.queue_draw()

由于评论太大,所以我添加了这个作为回应。
这个问题不是很清楚。您的意思是问如何使用cairo绘图来绘制到Gtk Widgets上?首先,没有GTK Pixbuf,我想你指的是GDK Pixbuf。GTK中的大部分绘图工作都是在GDK层完成的。如果您想了解有关窗口、绘图机制或图像操作的信息,您应该查看GDK以了解更多细节。这些链接有望帮助您了解cairo-gdk交互。虽然我对GTK、GDK的python绑定的经验;Cairo是nil,但是我认为如果您查找gdk-cairo sample, Google会为您提供一些很好的资源。
希望这对你有所帮助!

最新更新