根窗口
PyCairo 教程的這個部分,我們將與根窗口打交道。根窗口就是桌面窗口,通常也是我們放置圖標的地方。
控制根窗口是可能的。從程序員的角度來看,它僅僅是一種特殊的窗口。
透明窗口
我們的第一個例子將創建一個透明窗口。我們將看到窗口對象下面是什么東西。
#!/usr/bin/python''' ZetCode PyCairo tutorialThis code example shows how to create a transparent window.author: Jan Bodnar website: zetcode.com last edited: August 2012 '''import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk import cairoclass 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.CENTER)self.connect("delete-event", Gtk.main_quit)self.show_all()def tran_setup(self):self.set_app_paintable(True)screen = self.get_screen()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()def main():app = Example()Gtk.main()if __name__ == "__main__":main()為了創建透明窗口,我們獲取 screen 對象的 visual 值,并為我們的窗口設置它。在 on_draw() 方法中,我們在 screen 的 visual 對象上繪制。這創造了部分透明的錯覺。
self.set_app_paintable(True)我們必須將要繪制的應用設置為 on。
screen = self.get_screen()get_screen() 方法返回 screen 對象。
visual = screen.get_rgba_visual()從 screen 窗口,我們獲取它的 visual。這個 visual 包含一些底層的顯示信息。
if visual != None and screen.is_composited():self.set_visual(visual)不是所有的顯示器都支持這種操作。然而,我們檢查我們的屏幕是否支持組合,并且返回的 visual 不是 None。我們將屏幕的 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()我們使用部分透明的 source 在屏幕窗口上繪制。cairo.OPERATOR_SOURCE 創建一個組合操作,我們以此用 source 來繪制,其中 source 為屏幕窗口。為了獲取完全的透明,我們把 alpha 值設置為 0,或者使用 cairo.OPERATOR_CLEAR 操作符。
截屏
根窗口在截屏時也是必須的。
#!/usr/bin/python''' ZetCode PyCairo tutorialThis code example takes a screenshot.author: Jan Bodnar website: zetcode.com last edited: August 2012 '''import gi gi.require_version('Gdk', '3.0') from gi.repository import Gdk import cairodef main():root_win = Gdk.get_default_root_window()width = root_win.get_width()height = root_win.get_height()ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)pb = Gdk.pixbuf_get_from_window(root_win, 0, 0, width, height)cr = cairo.Context(ims)Gdk.cairo_set_source_pixbuf(cr, pb, 0, 0)cr.paint()ims.write_to_png("screenshot.png")if __name__ == "__main__":main()這個例子截取整個屏幕的快照。
root_win = Gdk.get_default_root_window()我們通過 Gdk.get_default_root_window() 方法調用獲得根窗口。
width = root_win.get_width()height = root_win.get_height()我們確定根窗口的寬度和高度。
ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)創建一個空的圖像 surface。它的大小與根窗口一致。
pb = Gdk.pixbuf_get_from_window(root_win, 0, 0, width, height)我們使用 Gdk.pixbuf_get_from_window() 方法調用由根窗口獲取一個 pixbuf。pixbuf是在內存中描述圖片的對象。它由 GTK 庫使用。
cr = cairo.Context(ims)Gdk.cairo_set_source_pixbuf(cr, pb, 0, 0)cr.paint()在上面的這幾行代碼中,我們基于前面創建的圖片 surface 創建一個 Cairo 繪制上下文。我們把 pixbuf 放進繪制上下文,并且將它繪制到 surface 上。
ims.write_to_png("screenshot.png")使 write_to_png() 方法將圖片 surface 寫入一個 PNG 圖片文件。
展示消息
在第三個例子中,我們將在桌面窗口中顯示一條信息。
#!/usr/bin/python''' ZetCode PyCairo tutorialThis code example shows a message on the desktop window.author: Jan Bodnar website: zetcode.com last edited: August 2012 '''import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, Gdk, Pango import cairoclass Example(Gtk.Window):def __init__(self):super(Example, self).__init__()self.setup()self.init_ui()def setup(self):self.set_app_paintable(True)self.set_type_hint(Gdk.WindowTypeHint.DOCK)self.set_keep_below(True)screen = self.get_screen()visual = screen.get_rgba_visual()if visual != None and screen.is_composited():self.set_visual(visual)def init_ui(self):self.connect("draw", self.on_draw)lbl = Gtk.Label()text = "ZetCode, tutorials for programmers."lbl.set_text(text)fd = Pango.FontDescription("Serif 20")lbl.modify_font(fd)lbl.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse("white"))self.add(lbl)self.resize(300, 250)self.set_position(Gtk.WindowPosition.CENTER)self.connect("delete-event", Gtk.main_quit)self.show_all()def on_draw(self, wid, cr):cr.set_operator(cairo.OPERATOR_CLEAR)cr.paint()cr.set_operator(cairo.OPERATOR_OVER)def main():app = Example()Gtk.main()if __name__ == "__main__":import signalsignal.signal(signal.SIGINT, signal.SIG_DFL)main()這段代碼在根窗口上顯示一條消息標簽。
self.set_app_paintable(True)我們將管理應用窗口,所以使它為 paintable。
self.set_type_hint(Gdk.WindowTypeHint.DOCK)實現這個窗口 hint 移除窗口邊界和裝飾。
self.set_keep_below(True)我們使應用總是在底部,只在根窗口上方。
screen = self.get_screen()visual = screen.get_rgba_visual()if visual != None and screen.is_composited():self.set_visual(visual)我們將屏幕的 visual 設為我們的應用程序的 visual。
lbl = Gtk.Label()text = "ZetCode, tutorials for programmers."lbl.set_text(text)我們在應用程序窗口上放一條消息標簽。
fd = Pango.FontDescription("Serif 20")lbl.modify_font(fd)lbl.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse("white"))借助于 Pango 模塊,我們改變文字的外觀。
def on_draw(self, wid, cr):cr.set_operator(cairo.OPERATOR_CLEAR)cr.paint()cr.set_operator(cairo.OPERATOR_OVER)我們使用 cairo.OPERATOR_CLEAR 操作符清除窗口的背景。然后我們設置cairo.OPERATOR_CLEAR 來繪制標簽 widget。
if __name__ == "__main__":import signalsignal.signal(signal.SIGINT, signal.SIG_DFL)main()有一個老 bug 使得我們無法通過 Ctrk+C 快捷鍵終止由終端啟動的應用程序。添加這兩行代碼是對這種情況的一種workaround 做法。
在這一章中,我們討論了 PyCairo 中的桌面窗口。
原文
Done.
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
- 上一篇: PyCairo 中的图片
- 下一篇: PyCairo 教程