开罗的背景和坚持?

发布于 2024-09-15 10:11:02 字数 2239 浏览 9 评论 0原文

我刚刚开始使用 pycairo,遇到了以下有趣的错误。我编写的程序创建一个简单的 gtk 窗口,在其上绘制一个矩形,然后有一个回调在任何类型的键盘输入上绘制随机线。然而,似乎对于每个键盘输入,我都必须创建一个新的上下文,否则在程序收到第一个键盘输入时会出现错误(特别是在 .lines() 行上)。如果重要的话,错误如下。 'BadDrawable(无效的像素图或窗口参数)'。 (详细信息:serial 230 error_code 9 request_code 53minor_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)

感谢您的帮助!

(更新:我在玩,我意识到以下内容:当我调整窗口大小时,添加的所有新对象都会被删除(或者至少不再出现?))

I am just getting started using pycairo, and I ran into the following interesting error. The program I write creates a simple gtk window, draws a rectangle on it, and then has a callback to draw a random line on any kind of keyboard input. However, it seems that with each keyboard input, I have to create a new context, or I get an error at the moment the program receives first keyboard input (specifically, on the .stroke() line). Error is as follows, if it matters. 'BadDrawable (invalid Pixmap or Window parameter)'. (Details: serial 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)

Thanks for your help!

(Update: I was playing around, and I realized the following: when I resize the window, all new objects that were added get deleted (or at least don't appear anymore?) )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

メ斷腸人バ 2024-09-22 10:11:02

开罗的图画根本不会持久。 (最好不要将它们视为“对象”——它不像画布库,您可以在绘制它们后移动它们或转换它们。)您必须在公开处理程序中完成所有绘制,否则它正如您所发现的,只要重新绘制窗口,它就会消失。

由于双缓冲,开罗上下文不会持续存在:请参阅 C 文档中的注释,不幸的是我在 PyGTK 文档中找不到任何地方。

在上面的代码中,您应该在按键处理程序中生成随机线的坐标和颜色并将它们保存在数组中。然后在暴露处理程序中,按顺序绘制数组中的每一行。

Cairo drawings don't persist at all. (It's best not to think of them as "objects" -- it's not like a canvas library where you can move them around or transform them after you've drawn them.) You have to do all drawing in the expose handler, or it will, as you have found out, disappear whenever the window is redrawn.

The cairo context doesn't persist because of double buffering: see the note in the C documentation, which unfortunately I couldn't find anywhere in the PyGTK documentation.

In the above code, you should generate the coordinates and color of your random line in the keypress handler and save them in an array. Then in the expose handler, draw each line in the array in order.

送君千里 2024-09-22 10:11:02

虽然您必须在每次运行时创建上下文,但您可以通过禁用小部件的双缓冲来实现您正在寻找的持久性。

这是一个使用仓鼠图形库的示例:

https://github.com /projecthamster/experiments/blob/master/many_lines.py

while you have to create context on every run, you can achieve the persistence you are looking for by disabling the double buffering of the widget.

here's an example using hamster graphics library that just does that:

https://github.com/projecthamster/experiments/blob/master/many_lines.py

ぇ气 2024-09-22 10:11:02

需要讨论的多种持久性:

某些表面上的绘图不会持久:GUI 表面。您应该在公开回调中重新绘制它们。

PyCairo 对象不应被视为持久对象,而只能被视为 C 中 Cairo 库的函数的接口。Cairo

上下文的内容(路径和填充)不会在行程()或填充()操作之外持续存在。

GUI 表面的上下文在暴露事件之间不会持续存在(因为双缓冲?)(我不知道其他表面(即设备)的上下文是否持续存在。)因此您不能使用 cairo 上下文来存储属性视口(文档上的窗口,即用户坐标中的模型)的视图。

视觉暂留是人眼在光线停止后看到光线的倾向。重影和闪烁是动画或视频中的症状。禁用双缓冲可以让您看到绘制的内容,即在一个暴露事件中启用动画(视觉持久性症状的模拟)。禁用双缓冲不会使 GUI 表面上的上下文在暴露事件之间保持持久。

记忆的持久才是真正的持久,或者说超现实的持久。

Many flavors of persistence to discuss:

Drawings on some surfaces don't persist: GUI surfaces. You should redraw them in the expose callback.

PyCairo objects shouldn't be treated as persistent objects, only as an interface to functions of the Cairo library in C.

The contents (paths and fills) of Cairo contexts don't persist beyond a stroke() or fill() operation.

A context for a GUI surface doesn't persist between expose events (because of double buffering?) (I don't know whether a context persists for other surfaces i.e. devices.) So you can't use a cairo context to store the attributes of a viewport (a window onto a document i.e. model in user coordinates.)

Visual persistence is the tendency of the human eye to see light after it has ceased. Ghosts and flicker are its symptoms in animation or video. Disabling double buffering lets you see things as they are drawn, that is, enabling animation within one expose event ( the simulation of the symptoms of visual persistence.) Disabling double buffering doesn't make a context on a GUI surface persistent between expose events.

The persistence of memory is the ur real persistence, or should I say surreal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文