【问题标题】:Pycairo: How to correctly instance cairo.XlibSurface()?Pycairo:如何正确实例化 cairo.XlibSurface()?
【发布时间】:2020-08-26 21:58:33
【问题描述】:

我正在尝试使用 Pycairo 创建小部件来监控系统,例如 Conky。 我正在尝试直接在 X 上绘图,使用带有 Xlib 的 Cairo Surface。

当我尝试实例化 cairo.XlibSurface() 类时,返回错误:

TypeError: The XlibSurface type cannot be directly instantiated

我的简单代码:

import cairo
surface = cairo.XlibSurface()

如何正确实例化 cairo.XlibSurface() ?

提前致谢

【问题讨论】:

  • 没有简单的方法 - 也许你最好通过 GTK 使用 Cairo - 在这里可以看到一个最新的例子:pygobject.readthedocs.io/en/latest/guide/cairo_integration.html
  • 使用 gtk 很容易,但我想与 xlib 集成并在 X 而不是 gtk 窗口中绘制。我找不到任何带有 xlib 的 pycairo 示例。

标签: python cairo xlib pycairo


【解决方案1】:

[不是一个完整的答案] 我有足够的 sn-ps,这可能比作为评论更有用。很抱歉没有深入了解这一点。

documentation for PyCairo XlibSurface 本身只提到它可以通过对 GTK 的某些调用来实例化 - 我不确定这是否只是对 GTK2 的旧绑定。我可以使用 GTK +3 找到一个 sn-p 来获取 Cairo 上下文,但如果不求助于 ctypes,从 Cairo 上下文返回到它使用的 Surface 似乎是不可行的。

因此,您基本上需要使用 Python ctypes 调用 Cairo's C cairo_xlib_surface_create,并从上述函数返回的指针中找到使用 ctypes 创建 Python cairo.XlibSurface 实例的方法。这就是您可能必须在 pygtk 遗留代码库、C 语言中找到并在 Python 代码中使用 ctypes 复制的“缺失环节”。

至于首先调用cairo_xlib_surface_create 所需的参数,您可能可以使用Python XLib 获取它们 - 下面的sn-p 为您提供了一个Window GID 和用于X Display 和Window 的Python 包装器:

from Xlib import X, display
pd = display.Display()
win = pd.screen().root.create_window(0, 0, 640, 480, 0, pd.screen().root_depth, X.InputOutput, X.CopyFromParent)
win.map()
pd.sync()

xid = xx.__resource__()

【讨论】:

  • 感谢您的回答,但没有解决我的问题。我使用带有Gdk.WindowTypeHint.DESKTOP 的Gtk Window 解决了它。
【解决方案2】:

未解决问题:如何将 Pycairo 与 Xlib 一起使用,但使用 Gtk 和 Pycairo 是一个优雅的替代方案。

如何将 Pycairo 与 Xlib 一起使用的谜团仍在继续。

使用带有Gdk.WindowTypeHint.DESKTOP的Gtk窗口,得到优雅的输出。

import gi
gi.require_versions({
    'Gdk':  '3.0',
    'Gtk':  '3.0',
    'Wnck': '3.0',
    'Gst':  '1.0',
    'AppIndicator3': '0.1',
})

from gi.repository import Gtk, Gdk
import cairo


class Example(Gtk.Window):

    def __init__(self):
        super(Example, self).__init__()

        self.tran_setup()
        self.init_ui()

    def init_ui(self):
        self.connect("draw", self.on_draw)
        # self.set_title("Transparent window")
        self.resize(300, 250)
        self.set_position(Gtk.WindowPosition.NONE)
        self.move(0, 40)
        self.connect("delete-event", Gtk.main_quit)
        
        # The magic is here
        self.set_type_hint(Gdk.WindowTypeHint.DESKTOP)

        self.show_all()

    def tran_setup(self):
        self.set_app_paintable(True)
        screen = self.get_screen()

        #print(self.get_type_hint())

        visual = screen.get_rgba_visual()
        if visual != None and screen.is_composited():
            self.set_visual(visual)

    def on_draw(self, wid, cr):
        cr.set_source_rgba(0.2, 0.2, 0.2, 0.4)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.paint()

        cr.set_source_rgb(0.6, 0.6, 0.6)

        cr.rectangle(20, 20, 120, 80)
        cr.fill()

        self.draw(cr)

    def draw(self, cr):
        cr.set_source_rgb(0, 256, 256)
        cr.rectangle(180, 20, 80, 80)
        cr.fill()


def main():
    app = Example()
    Gtk.main()


if __name__ == "__main__":
    main()

输出:

【讨论】:

    猜你喜欢
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 2018-02-05
    • 2019-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多