原文: https://zetcode.com/gfx/pycairo/root/

在 PyCairo 教程的这一部分中,我们将使用根窗口。 根窗口是我们通常具有图标快捷方式的桌面窗口。

可以使用根窗口进行操作。 从程序员的角度来看,它只是一种特殊的窗口。

透明窗口

我们的第一个示例将创建一个透明窗口。 我们将看到窗口对象下方的内容。

  1. #!/usr/bin/python
  2. '''
  3. ZetCode PyCairo tutorial
  4. This code example shows how to
  5. create a transparent window.
  6. author: Jan Bodnar
  7. website: zetcode.com
  8. last edited: August 2012
  9. '''
  10. from gi.repository import Gtk
  11. import cairo
  12. class Example(Gtk.Window):
  13. def __init__(self):
  14. super(Example, self).__init__()
  15. self.tran_setup()
  16. self.init_ui()
  17. def init_ui(self):
  18. self.connect("draw", self.on_draw)
  19. self.set_title("Transparent window")
  20. self.resize(300, 250)
  21. self.set_position(Gtk.WindowPosition.CENTER)
  22. self.connect("delete-event", Gtk.main_quit)
  23. self.show_all()
  24. def tran_setup(self):
  25. self.set_app_paintable(True)
  26. screen = self.get_screen()
  27. visual = screen.get_rgba_visual()
  28. if visual != None and screen.is_composited():
  29. self.set_visual(visual)
  30. def on_draw(self, wid, cr):
  31. cr.set_source_rgba(0.2, 0.2, 0.2, 0.4)
  32. cr.set_operator(cairo.OPERATOR_SOURCE)
  33. cr.paint()
  34. def main():
  35. app = Example()
  36. Gtk.main()
  37. if __name__ == "__main__":
  38. main()

为了创建透明窗口,我们获得了屏幕对象的视觉效果并将其设置为我们的窗口。 在on_draw()方法中,我们绘制屏幕的可视对象。 这造成了部分透明的幻觉。

  1. self.set_app_paintable(True)

我们必须设置要绘制的应用。

  1. screen = self.get_screen()

get_screen()方法返回屏幕对象。

  1. visual = screen.get_rgba_visual()

从屏幕窗口中,我们可以看到它。 视觉内容包含低级显示信息。

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

并非所有的显示器都支持此操作。 因此,我们检查屏幕是否支持合成并且返回的视觉效果不是NULL。 我们将屏幕的视觉效果设置为窗口的视觉效果。

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

我们使用部分透明的源来绘制屏幕窗口。 cairo.OPERATOR_SOURCE在我们绘制源代码的地方创建了合成操作。 这是屏幕窗口。 为了获得完全透明,我们将 alpha 值设置为 0 或使用cairo.OPERATOR_CLEAR运算符。

根窗口 - 图1

图:透明窗口

截屏

根窗口对于截图也是必不可少的。

  1. #!/usr/bin/python
  2. '''
  3. ZetCode PyCairo tutorial
  4. This code example takes a screenshot.
  5. author: Jan Bodnar
  6. website: zetcode.com
  7. last edited: August 2012
  8. '''
  9. from gi.repository import Gdk
  10. import cairo
  11. def main():
  12. root_win = Gdk.get_default_root_window()
  13. width = root_win.get_width()
  14. height = root_win.get_height()
  15. ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
  16. pb = Gdk.pixbuf_get_from_window(root_win, 0, 0, width, height)
  17. cr = cairo.Context(ims)
  18. Gdk.cairo_set_source_pixbuf(cr, pb, 0, 0)
  19. cr.paint()
  20. ims.write_to_png("screenshot.png")
  21. if __name__ == "__main__":
  22. main()

该示例捕获整个屏幕的快照。

  1. root_win = Gdk.get_default_root_window()

我们通过Gdk.get_default_root_window()方法调用获得了根窗口。

  1. width = root_win.get_width()
  2. height = root_win.get_height()

我们确定根窗口的宽度和高度。

  1. ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)

空的图像表面被创建。 它具有根窗口的大小。

  1. pb = Gdk.pixbuf_get_from_window(root_win, 0, 0, width, height)

我们使用Gdk.pixbuf_get_from_window()方法调用从根窗口中获得一个pixbufpixbuf是描述内存中图像的对象。 GTK 库使用它。

  1. cr = cairo.Context(ims)
  2. Gdk.cairo_set_source_pixbuf(cr, pb, 0, 0)
  3. cr.paint()

在上述代码行中,我们在之前创建的图像表面上创建了 Cairo 绘图上下文。 我们将 pixbuf 放在绘图上下文上并将其绘制在表面上。

  1. ims.write_to_png("screenshot.png")

使用write_to_png()方法将图像表面写入 PNG 图像。

显示信息

在第三个示例中,我们将在桌面窗口上显示一条消息。

  1. #!/usr/bin/python
  2. '''
  3. ZetCode PyCairo tutorial
  4. This code example shows a message on the desktop
  5. window.
  6. author: Jan Bodnar
  7. website: zetcode.com
  8. last edited: August 2012
  9. '''
  10. from gi.repository import Gtk, Gdk, Pango
  11. import cairo
  12. class Example(Gtk.Window):
  13. def __init__(self):
  14. super(Example, self).__init__()
  15. self.setup()
  16. self.init_ui()
  17. def setup(self):
  18. self.set_app_paintable(True)
  19. self.set_type_hint(Gdk.WindowTypeHint.DOCK)
  20. self.set_keep_below(True)
  21. screen = self.get_screen()
  22. visual = screen.get_rgba_visual()
  23. if visual != None and screen.is_composited():
  24. self.set_visual(visual)
  25. def init_ui(self):
  26. self.connect("draw", self.on_draw)
  27. lbl = Gtk.Label()
  28. text = "ZetCode, tutorials for programmers."
  29. lbl.set_text(text)
  30. fd = Pango.FontDescription("Serif 20")
  31. lbl.modify_font(fd)
  32. lbl.modify_fg(Gtk.StateFlags.NORMAL,Gdk.color_parse("white"))
  33. self.add(lbl)
  34. self.resize(300, 250)
  35. self.set_position(Gtk.WindowPosition.CENTER)
  36. self.connect("delete-event", Gtk.main_quit)
  37. self.show_all()
  38. def on_draw(self, wid, cr):
  39. cr.set_operator(cairo.OPERATOR_CLEAR)
  40. cr.paint()
  41. cr.set_operator(cairo.OPERATOR_OVER)
  42. def main():
  43. app = Example()
  44. Gtk.main()
  45. if __name__ == "__main__":
  46. import signal
  47. signal.signal(signal.SIGINT, signal.SIG_DFL)
  48. main()

该代码在根窗口上显示消息标签。

  1. self.set_app_paintable(True)

我们将操纵应用窗口,因此我们使其可绘制。

  1. self.set_type_hint(Gdk.WindowTypeHint.DOCK)

实现此窗口提示会删除窗口边框和装饰。

  1. self.set_keep_below(True)

我们始终将应用始终放在根窗口的底部。

  1. screen = self.get_screen()
  2. visual = screen.get_rgba_visual()
  3. if visual != None and screen.is_composited():
  4. self.set_visual(visual)

我们将屏幕的外观设置为应用的外观。

  1. lbl = Gtk.Label()
  2. text = "ZetCode, tutorials for programmers."
  3. lbl.set_text(text)

我们在应用窗口上放置一个消息标签。

  1. fd = Pango.FontDescription("Serif 20")
  2. lbl.modify_font(fd)
  3. lbl.modify_fg(Gtk.StateFlags.NORMAL,Gdk.color_parse("white"))

在 Pango 模块的帮助下,我们更改了文本的外观。

  1. def on_draw(self, wid, cr):
  2. cr.set_operator(cairo.OPERATOR_CLEAR)
  3. cr.paint()
  4. cr.set_operator(cairo.OPERATOR_OVER)

我们使用cairo.OPERATOR_CLEAR运算符清除窗口背景。 然后我们设置cairo.OPERATOR_CLEAR以绘制标签窗口小部件。

  1. if __name__ == "__main__":
  2. import signal
  3. signal.signal(signal.SIGINT, signal.SIG_DFL)
  4. main()

有一个较旧的错误,该错误不允许我们使用 Ctrl + C 快捷方式终止从终端启动的应用。 为此添加两行是一种解决方法。

根窗口 - 图2

图:根窗口上的消息

在本章中,我们使用了 PyCairo 中的桌面窗口。