在Fedora 24上的Python3中使用“cairo.Region”时出现分段错误
我正试图获得一个应用于窗口的输入形状,这样我就可以有一个透明的框架,其中只有感兴趣的部分可以点击,等等 我将Cairo图形与PyGObject(python3)一起使用 该对象是一个常规Gtk Windows对象,然后该对象定义了一个Cairo绘图区域:在Fedora 24上的Python3中使用“cairo.Region”时出现分段错误,python,python-3.x,gtk,pygobject,pycairo,Python,Python 3.x,Gtk,Pygobject,Pycairo,我正试图获得一个应用于窗口的输入形状,这样我就可以有一个透明的框架,其中只有感兴趣的部分可以点击,等等 我将Cairo图形与PyGObject(python3)一起使用 该对象是一个常规Gtk Windows对象,然后该对象定义了一个Cairo绘图区域: class Face(Gtk.Window): def __init__(self): super(Face, self).__init__() self.init_ui() def init_
class Face(Gtk.Window):
def __init__(self):
super(Face, self).__init__()
self.init_ui()
def init_ui(self):
[...]
self.darea = Gtk.DrawingArea()
self.darea.connect("draw", self.on_draw)
self.add(self.darea)
def on_draw(self, widget, cr):
[... (drawing a couple shapes into the context)]
sface = cr.get_group_target()
mregion = Gdk.cairo_region_create_from_surface(sface)
# the above line produces the error
# the following lines is wishful thinking at this point...
#self.get_window().input_shape_combine_region(mregion, 0, 0)
因此,每当必须重新绘制绘图区域时,即当窗口被移动、调整大小、隐藏后显示等时,都会调用函数on_draw()
窗口的大部分实际上是空的,因为它应该是一个半透明的框架,只有可见的部分应该是可点击的。
但是,我得到了以下错误:
Traceback (most recent call last):
File "./lsc.py", line 236, in on_draw
mregion = Gdk.cairo_region_create_from_surface(sface)
TypeError: Couldn't find foreign struct converter for 'cairo.Region'
python3: cairo-surface.c:953: cairo_surface_destroy: Assertion `CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)' failed.
zsh: abort (core dumped) ./lsc.py
Python3、PyGObject和Cairo libs的软件包已经安装,我还导入了Cairo的两个部分:
from gi.repository import Gtk, Gdk, cairo
import cairo
在这一点上,我不完全确定这是一个Python问题,还是我自己的错误。
我不确定使用cairo.Region是否也适用,我下面举的例子是:
编辑 在这一点上,我很困惑到底发生了什么。我一直在研究这个问题,这就是我发现的: 和开罗之间似乎存在某种错误 当我只使用开罗的内省部分时:
from gi.repository import Gtk, Gdk, cairo
#import cairo
然后运行我的脚本,我得到以下错误:
raceback (most recent call last):
File "./lsc.py", line 164, in on_draw
cr.set_operator(cairo.OPERATOR_SOURCE)
File "/usr/lib64/python3.5/site-packages/gi/module.py", line 139, in __getattr__
self.__name__, name))
AttributeError: 'gi.repository.cairo' object has no attribute 'OPERATOR_SOURCE'
显然,我在代码中使用cairo.OPERATOR\u SOURCE
来绘制cairo上下文。然而,内省包似乎甚至不包含用于在曲面上绘制的te操作符。很奇怪
当我只使用非内省模块时:
from gi.repository import Gtk, Gdk
import cairo
我得到的错误与问题的第一部分相同
最后,这是我目前安装的cairo软件包列表:
cairo-devel-1.14.6-1.fc24.x86_64
pycairo-devel-1.10.0-4.fc24.x86_64
cairo-gobject-1.14.6-1.fc24.i686
mingw32-cairo-1.14.6-1.fc24.noarch
python3-cairocffi-0.7.2-5.fc24.noarch
cairo-1.14.6-1.fc24.i686
cairo-1.14.6-1.fc24.x86_64
pycairo-1.10.0-4.fc24.x86_64
python3-cairosvg-1.0.19-3.fc24.noarch
cairomm-devel-1.12.0-2.fc24.x86_64
cairo-clock-0.3.4-17.fc24.x86_64
cairomm-1.12.0-2.fc24.x86_64
cairo-gobject-1.14.6-1.fc24.x86_64
python3-cairo-1.10.0-15.fc24.x86_64
mingw32-cairomm-1.12.0-2.fc24.noarch
python3-cairo-devel-1.10.0-15.fc24.x86_64
cairo-gobject-devel-1.14.6-1.fc24.x86_64
我想你会发现,所有这些都是最近才出现的,并且符合我上面链接的示例中所述的要求
也请考虑以下的268—274行:
作者没有使用内省的cairo
,他只是导入cairo,这让我相信这可能是更正确的方法
总之,整个脚本也不起作用
在这一点上,我又被卡住了。我似乎找不到关于如何使用此功能的最新和/或工作示例
到目前为止,似乎使用cairo
的内省版本没有任何用处,因为它几乎没有定义原始版本的任何元素。但是,当使用常规的pycairo
(通过导入import cairo
)时,我得到了一个错误,使我首先发布了这个问题
我开始相信我有一个概念上的错误,也许?好吧。。。我知道这篇文章有点过时,但我是在寻找同一个问题的答案时发现的。(这是我对堆栈溢出的第一个贡献,请耐心等待)。我想在GTK3中创建一个非矩形窗口,经过数小时的研究,我也发现它是空的 最后,我找到了与上面提到的Polemon相同的示例程序,并通读了Cairo和Gdk文档。最后,这两个函数实现了创建非矩形窗口的目标,该窗口只响应Cairo曲面的非透明区域上的输入 现在,重点介绍使用GtkDialog窗口创建应用程序启动器,但此代码可以应用于标准GTKWindow 以下是我为达到这一效果而采取的步骤。首先,我在对话框窗口的构造函数中添加了以下行:
self.set_decorated(False) # Creates a borderless window without a title bar
self.set_app_paintable(True) # Tells GTK not to redraw the window area but let the application handle the drawing
self.connect('draw', self.draw) # Registers a callback function for the draw signal
接下来,我定义了负责处理draw信号的回调函数。我在信中说:
# Create a Cairo surface from a PNG image
self.image = cairo.ImageSurface.create_from_png("image-with-transparent-regions.png")
# Create a new Cairo region based on this Cairo surface
region = Gdk.cairo_region_create_from_surface(self.image)
# Combine this region with the window dialog window region.
# Input area is now restricted to non-transparent areas of the dialog window
self.input_shape_combine_region(region)
# Sets the Cairo compositing Operator to replace the contents of the window background
context.set_operator(cairo.OPERATOR_SOURCE)
# Sets the Cairo surface as the pattern to be drawn on the window background
context.set_source_surface(self.image, 0, 0)
# Paints the background image with the Cairo surface pattern
context.paint()
# Restores the default state of the Cairo compositing operator to draw the source layer on top of the destination window layer.
# This prevents the background image from being erased by alpha component of the widgets being drawn on top of it.
context.set_operator(cairo.OPERATOR_OVER)
对于任何有兴趣尝试随时可以运行的代码的人,.您使用的是什么版本的pycairo?您在示例中看到了吗?@oldtechaa看起来是这样的:pycairo-1.10.0-4.fc24.x8664(版本1.10.0)。不过,我会仔细看看bug报告中链接的示例。@oldtechaa好吧,我有正确的版本,或者我分别满足了版本要求,但错误仍然在发生。所以我不知道…@oldtechaa
dnf install pycairo pycairo devel
常规Fedora repos等。我没有太多使用cairo,但我可以确认,从gi.repository import cairo导入的是完全无用的。另外,我在cairo文档中注意到了这一点:,所以也许你应该检查一下情况是否如此。
# Create a Cairo surface from a PNG image
self.image = cairo.ImageSurface.create_from_png("image-with-transparent-regions.png")
# Create a new Cairo region based on this Cairo surface
region = Gdk.cairo_region_create_from_surface(self.image)
# Combine this region with the window dialog window region.
# Input area is now restricted to non-transparent areas of the dialog window
self.input_shape_combine_region(region)
# Sets the Cairo compositing Operator to replace the contents of the window background
context.set_operator(cairo.OPERATOR_SOURCE)
# Sets the Cairo surface as the pattern to be drawn on the window background
context.set_source_surface(self.image, 0, 0)
# Paints the background image with the Cairo surface pattern
context.paint()
# Restores the default state of the Cairo compositing operator to draw the source layer on top of the destination window layer.
# This prevents the background image from being erased by alpha component of the widgets being drawn on top of it.
context.set_operator(cairo.OPERATOR_OVER)