[翻译]PyCairo指南--根窗口

根窗口

PyCairo指南的这个部分,我们将与根窗口打交道。根窗口就是桌面窗口,通常也是我们放置图标的地方。

通过根窗口来控制也是可能的。从程序员的角度来看,它仅仅是一种特殊的一个窗口。

透明窗口

我们的第一个例子将创建一个透明窗口。我们将看到窗口对象下面是什么东西。

#!/usr/bin/python
'''
ZetCode PyCairo tutorial

This code example shows how to 
create a transparent window. 

author: Jan Bodnar
website: zetcode.com
last edited: August 2012
'''

from gi.repository import Gtk
import cairo

class MainWindow(Gtk.Window):
    def __init__(self):
        super(self.__class__, 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, wdith, cr):
        cr.set_source_rgba(0.2, 0.2, 0.2, 0.4)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.paint()


def main():
    window = MainWindow()
    Gtk.main()
        
if __name__ == "__main__":
    main()

为了创建一个透明的窗口,我们获取screen对象的visual值,并为我们的on_draw()方法设置它,我们在screen的visual对象上来画。这将创建一种假想的透明。

        self.set_app_paintable(True)

我们必须设置应用paintable值为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是非空的。我们将屏幕的visual设为我们的窗口的visual。

    def on_draw(self, wdith, 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操作。

[翻译]PyCairo指南--根窗口_第1张图片

Figure: Transparent window

截屏

根窗口在截屏时也是需要的。

#!/usr/bin/python
'''
ZetCode PyCairo tutorial

This code example takes a screenshot. 

author: Jan Bodnar
website: zetcode.com
last edited: August 2012
'''

from gi.repository import Gdk
import cairo

def 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()

在上面的这几行code中,我们基于前面创建的图片surface创建了一个Cairo绘制上下文。我们把pixbuf放进绘制上下文,并且将它绘制到surface上。

    ims.write_to_png("screenshot.png")

使write_to_png()方法将图片surface写如一个PNG图片。

Showing message

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

#!/usr/bin/python

'''
ZetCode PyCairo tutorial

This code example shows a message on the desktop
window. 

author: Jan Bodnar
website: zetcode.com
last edited: August 2012
'''

from gi.repository import Gtk, Gdk, Pango
import cairo

class MainWindow(Gtk.Window):
    def __init__(self):
        super(self.__class__, self).__init__()
        self.setup()
        self.init_ui()

    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 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 on_draw(self, wdith, cr):
        cr.set_operator(cairo.OPERATOR_CLEAR)
        cr.paint()
        cr.set_operator(cairo.OPERATOR_OVER)


def main():
    window = MainWindow()
    Gtk.main()
        
if __name__ == "__main__":
    import signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    main()

这段code在根窗口上显示一条消息标签。

        self.set_app_paintable(True)

我们将管理应用窗口,所以使它为paintable。

        self.set_type_hint(Gdk.WindowTypeHint.DOCK)

实现这个窗口hint移除窗口边界和装饰。

        self.set_keep_below(True)
We keep the application always at the bottom, just over the root window.我们保持应用总是在底部,只是在跟窗口上方。
        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, wdith, 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 signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    main()

有一个早先的bug 使得我们无法通过Ctrk+C快捷键来终止由终端启动的应用程序。添加这两行code是对这种情况的一种workaround的做法。

[翻译]PyCairo指南--根窗口_第2张图片

Figure: Message on the root window

在这一章中,我们讨论了PyCairo中的桌面窗口。

你可能感兴趣的:(python,graphics,cairo,RootWindow)