您现在的位置是:首页 > 编程 > 

Cairo context 和持久性

2025-07-27 02:10:47
Cairo context 和持久性 Cairo 是一个广泛使用的 2D 图形库,支持多种输出设备,包括屏幕、PDF、SVG等。Cairo 的核心是它的“context”(上下文)概念,这是进行所有绘制操作的中心点。在 Cairo 中,context 通常与特定的图形目标(或称作“surface”)关联,如窗口或图像文件。1、问题背景在使用 pycairo 绘制时,用户遇到了一个有趣的错误。该程序

Cairo context 和持久性

Cairo 是一个广泛使用的 2D 图形库,支持多种输出设备,包括屏幕、PDF、SVG等。Cairo 的核心是它的“context”(上下文)概念,这是进行所有绘制操作的中心点。在 Cairo 中,context 通常与特定的图形目标(或称作“surface”)关联,如窗口或图像文件。

1、问题背景

在使用 pycairo 绘制时,用户遇到了一个有趣的错误。该程序创建了一个简单的 GTK+ 窗口,在上面绘制一个矩形,然后有一个回调函数在键盘输入时绘制一条随机线条。但是,每次键盘输入时,用户都需要创建一个新的上下文,否则在程序收到第一个键盘输入时就会出现错误(特别是在 .stroke() 行上)。错误如下,如有必要。'BadDrawable (invalid Pixmap or Window parameter)'。

以下是代码的详细信息:

代码语言:javascript代码运行次数: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 respe 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._create()
    # Restrict Cairo to the exposed area; avoid extra work
    .rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
    .clip()
​
    self.draw(*self.window.get_size())
​
  def key_press_event(self, *args):
    # print args
     = self._create() # This is the line I have to add
    # in order to make this function not throw the error. ote that cr is only
    # given as attribute of self in order to stop it going out of scope when this line
    # doesn't exist
    .set_source_rgb(random.random(), random.random(), random.random())
    .move_to(*[z/2.0 for z in self.window.get_size()])
    .line_to(*[z*random.random() for z in self.window.get_size()])
    .stroke()
​
  def draw(self, width, height):
    # Fill the background with gray
    .set_source_rgb(.5,.5,.5)
    .rectangle(0, 0, width,height)
    .fill()
​
    .set_source_rgb(1,0,0)
    .arc(width/2.0, height/2.0, min(width,height)/2.0 - 20.0, 0.0, 2.0*math.pi)
    .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()
  ("delete-event", _quit)
  ('key-press-event',widget.key_press_event)
  widget.show()
  window.add(widget)
  window.present()
  ()
​
if __name__ == "__main__":
  run(Screen)

2、解决方案一:

不使用双缓冲

Cairo 图形无法持久保存。因此,您需要在曝光处理程序中完成所有绘制,否则,正如您已经发现的那样,它将在每次窗口重绘时消失。 Cairo 上下文不会持久存在,因为使用了双缓冲:请参阅 C 文档中的注释,不幸的是,我在 PyGTK 文档中不到任何地方。 在上面的代码中,您应该在按键处理程序中生成随机线的坐标和颜,并将它们保存在一个数组中。然后在曝光处理程序中,按顺序绘制数组中的每条线。 代码实现如下:

代码语言:javascript代码运行次数:0运行复制
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 respe to an expose-event
  __gsignals__ = { "expose-event": "override" }
​
  def __init__(self):
      super(Screen, self).__init__()
      # Create an array to store the coordinates and color of the random lines
      self.lines = []
​
  # Handle the expose-event by drawing
  def do_expose_event(self, event):
    # Create the cairo context
     = self._create()
    # Restrict Cairo to the exposed area; avoid extra work
    .rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
    .clip()
​
    # Draw the background with gray
    .set_source_rgb(.5,.5,.5)
    .rectangle(0, 0, width, height)
    .fill()
​
    .set_source_rgb(1,0,0)
    .arc(width/2.0, height/2.0, min(width,height)/2.0 - 20.0, 0.0, 2.0*math.pi)
    .stroke()
​
    # Draw the random lines
    for line in self.lines:
      .set_source_rgb(*line['color'])
      .move_to(*line['start'])
      .line_to(*line['end'])
      .stroke()
​
  def key_press_event(self, *args):
    # Generate the coordinates and color of the random line
    start = [z/2.0 for z in self.window.get_size()]
    end = [z*random.random() for z in self.window.get_size()]
    color = [random.random(), random.random(), random.random()]
​
    # Add the line to the array
    self.lines.append({'start': start, 'end': end, 'color': color})
​
    # Queue a redraw of the widget
    self.queue_draw()
​
# Create a GTK+ window, attach to the exit button, and whatever is passed as arg becomes the body of the window.
def run(Widget):
  window = gtk.Window()
  widget = Widget()
  ("delete-event", _quit)
  ('key-press-event',widget.key_press_event)
  widget.show()
  window.add(widget)
  window.present()
  ()
​
if __name__ == "__main__":
  run(Screen)

解决方案二:

禁用双缓冲

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

在代码中,您可以调用 set_double_buffered(False) 方法来禁用双缓冲。 以下是使用 Hamster Graphics 库的一个示例,它可以满足您的要求:

代码语言:javascript代码运行次数:0运行复制
import hamster
from hamster import graphics
​
# Create a window
window = graphics.window(640, 480, "Many Lines")
​
# Disable double buffering
window.set_double_buffered(False)
​
# Create an array to store the lines
lines = []
​
# Draw a line when a key is pressed
def on_key_press(event):
  # Generate the coordinates and color of the random line
  start = [random.randint(0, window.width), random.randint(0, window.height)]
  end = [random.randint(0, window.width), random.randint(0, window.height)]
  color = [random.random(), random.random(), random.random()]
​
  # Add the line to the array
  lines.append({'start': start, 'end': end, 'color': color})
​
  # Draw the line
  graphics.set_color(*color)
  _to(*start)
  graphics.line_to(*end)
  graphics.stroke()
​
# Handle key press events
window.bind("<KeyPress>", on_key_press)
​
# Start the event loop
()

在这两个例子中,Cairo context 的持久性是通过将绘图结果保存到文件中实现的。这使得 Cairo 非常适合于需要高度图形处理和跨平台图形输出的应用程序。

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1202620.html

相关标签:无
上传时间: 2025-07-24 02:33:03
留言与评论(共有 11 条评论)
本站网友 在商言商
25分钟前 发表
*args)
本站网友 陈东灵
29分钟前 发表
height)
本站网友 沉默不是代表我的错
2分钟前 发表
start
本站网友 孕妇早期注意事项
24分钟前 发表
window = gtk.Window() widget = Widget() ("delete-event"
本站网友 你好的日语
5分钟前 发表
.5
本站网友 康佳led32hs11
7分钟前 发表
.5
本站网友 宣武门二手房
15分钟前 发表
0.0
本站网友 萌日
1分钟前 发表
cairo
本站网友 广州二手房
9分钟前 发表
start
本站网友 郑州房屋出租
27分钟前 发表
因为使用了双缓冲:请参阅 C 文档中的注释