题
我刚刚开始使用Pycairo,遇到了以下有趣的错误。我编写的程序创建一个简单的GTK窗口,在其上绘制矩形,然后在任何类型的键盘输入上绘制一个随机行。但是,似乎有了每个键盘输入,我必须创建一个新的上下文,或者目前程序收到第一个键盘输入的那一刻(特别是在.stroke()行上)。错误如下,如果很重要。 “ BadDrawable(无效的PixMap或窗口参数)”。 (详细信息:序列230 error_code 9 request_code 53 minor_code 0)
#! /usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk, gobject, cairo, math, random
# Create a GTK+ widget on which we will draw using Cairo
class Screen(gtk.DrawingArea):
# Draw in response to an expose-event
__gsignals__ = { "expose-event": "override" }
# Handle the expose-event by drawing
def do_expose_event(self, event):
# Create the cairo context
self.cr = self.window.cairo_create()
# Restrict Cairo to the exposed area; avoid extra work
self.cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
self.cr.clip()
self.draw(*self.window.get_size())
def key_press_event(self, *args):
# print args
self.cr = self.window.cairo_create() # This is the line I have to add
# in order to make this function not throw the error. Note that cr is only
# given as attribute of self in order to stop it going out of scope when this line
# doesn't exist
self.cr.set_source_rgb(random.random(), random.random(), random.random())
self.cr.move_to(*[z/2.0 for z in self.window.get_size()])
self.cr.line_to(*[z*random.random() for z in self.window.get_size()])
self.cr.stroke()
def draw(self, width, height):
# Fill the background with gray
self.cr.set_source_rgb(.5,.5,.5)
self.cr.rectangle(0, 0, width,height)
self.cr.fill()
self.cr.set_source_rgb(1,0,0)
self.cr.arc(width/2.0, height/2.0, min(width,height)/2.0 - 20.0, 0.0, 2.0*math.pi)
self.cr.stroke()
#create a gtk window, attach to exit button, and whatever is passed as arg becomes the body of the window. AWESOME
def run(Widget):
window = gtk.Window()
widget = Widget()
window.connect("delete-event", gtk.main_quit)
window.connect('key-press-event',widget.key_press_event)
widget.show()
window.add(widget)
window.present()
gtk.main()
if __name__ == "__main__":
run(Screen)
谢谢你的帮助!
(更新:我正在玩耍,我意识到以下内容:调整窗口大小时,所有添加的新对象都会被删除(或者至少不再出现?))
解决方案
开罗绘画根本不会持续。 (最好不要将它们视为“对象” - 它不像是帆布库,您可以在绘制它们后将它们移动或转换它们。)正如您发现的那样,每当窗口重新绘制时,都会消失。
开罗的上下文由于双重缓冲而不会持续存在:请参阅 在C文档中注意, ,不幸的是,我在Pygtk文档中找不到任何地方。
在上面的代码中,您应该在按键处理程序中生成随机线的坐标和颜色,然后将其保存在数组中。然后在露天处理程序中,按顺序绘制阵列中的每一行。
其他提示
当您必须在每次运行上创建上下文时,您可以通过禁用小部件的双重缓冲来实现所寻找的持久性。
这是使用仓鼠图形库的示例,该库可以做到这一点:
https://github.com/projecthamster/experiments/blob/master/many_lines.py
持久性的许多口味要讨论:
图纸上 一些 表面不持续:GUI表面。您应该在公开回调中重新绘制它们。
pycairo对象不应被视为持续的对象,仅是C中的Cairo库的接口。
开罗上下文的内容(路径和填充)不会超出行程()或填充()操作。
GUI表面的上下文在暴露事件之间不持续(由于双重缓冲?)(我不知道其他表面的上下文是否持续存在,即设备。)因此,您不能使用开罗上下文来存储属性视口(在用户坐标中的文档IE模型上的窗口。)
视觉持久性是人眼停止后看到光的趋势。幽灵和闪烁是动画或视频中的症状。禁用双重缓冲可让您看到它们在绘制时看到的东西,也就是说,在一个暴露事件中启用动画(模拟视觉持久性症状。)禁用双重缓冲并不能使GUI表面持久地持续曝光事件之间。
记忆的持久性是您的真正持久性,或者我应该说超现实。