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

2 投票
1 回答
2292 浏览
提问于 2025-04-17 04:40

为了我自己的学习和可能的教育用途,我想为Python和Cairo制作一个类似pygame的API。但我不想让它完全和pygame一样。我希望它能成为一个半静态的绘图平台,能够使用GTK/GDK显示一张或多张图片,并且我想模仿TiKZ(一个latex包)优秀的API设计原则。虽然PyGame的API还不错,但我对它不太满意。有一个特别的问题是,我希望这个包能通过将所有内容绘制到一个pixbuf(使用Cairo)来处理窗口刷新,并在窗口被遮挡时自动重绘这个pixbuf。这样,最终的程序员就不需要担心窗口刷新了。实际上,最终的程序员不应该需要写任何类或函数,只需要一行行简单的代码就能画出一个笑脸(比如说)。这个图形库也不需要像TkInter那样维护一个越来越长的形状对象列表。(至少,我希望Cairo不会违背我的意图。)

我在pycairo中成功地绘制了各种东西,并将输出到ImageMagick和Postscript。所以我对pycairo本身是没问题的。

不幸的是,我找到的cairo/gtk/pycairo/pygtk文档——我不知道它是为谁写的,但显然不是为我写的。目前,我是一个像Project Euler那样的程序员,而不是那种“5个超前沿的面向对象API”的程序员。我希望能看到清晰的操作说明,或者一个明确的示例。


好的,我接受了一个回答,因为它至少有点帮助。但这里简而言之,真正的问题是,GDK在你使用Cairo绘制东西时会创建一个临时双缓冲区。预计当你处理一个暴露事件时,你会重新绘制所有内容。但如果你有一个非常复杂的图像,这个过程会很慢,尤其是在Python中。所以如果Cairo能写入一个永久双缓冲区而不是临时的,那就太好了,然后这个永久双缓冲区会通过GDK暴露出来。许多开发者都想要解决这个问题。似乎有一个项目提供了一种解决方案,那就是Google Chromium——你有没有注意到在Linux上Google Chrome的窗口暴露效果有多好?所以我会查看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()

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

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

还有最后一件事,我需要刷新像素缓冲区和事件缓冲区。看起来实现这个的一种方法是window.queue_draw()

1 个回答

3

因为这个问题太复杂了,所以我把它作为回复来写。
问题不太清楚。你是想问怎么用cairo绘图在Gtk控件上画东西吗?首先,没有叫做GTK Pixbuf的东西,我想你是指GDK Pixbuf。大部分在GTK中绘图的内容都是在GDK层完成的。如果你想了解窗口、绘图机制或者图像处理,应该去看看GDK的详细信息。这些 链接希望能帮助你了解cairo和gdk之间的互动。虽然我对GTK、GDK和Cairo的Python绑定没有经验,但我觉得如果你在谷歌上搜索gdk-cairo示例,会找到一些不错的资源。
希望这至少能帮到你一点!

撰写回答