出于测试和文档目的,我想创建一个gtk.Window对象的屏幕截图。我正在关注一个基本的pygtk样本。我修改的示例如下所示:
import gtk
def main():
button = gtk.Button("Hello")
scroll_win = gtk.ScrolledWindow()
scroll_win.add(button)
win = gtk.Window(gtk.WINDOW_TOPLEVEL)
win.add(scroll_win)
win.show_all()
if win.is_drawable() is not True:
raise RuntimeError("Not drawable?")
width, height = win.get_size()
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8,
width, height)
screenshot = pixbuf.get_from_drawable(win, win.get_colormap(),
0, 0, 0, 0, width, height)
screenshot.save('screenshot.png', 'png')
if __name__ == '__main__':
main()
gtk.main()
调用get_from_drawable方法时,我最终会遇到错误。
TypeError: Gdk.Pixbuf.get_from_drawable() argument 1 must be gtk.gdk.Drawable, not gtk.Window
我合并到基本示例中的the screenshot example显然是使用了一个继承自gtk.gdk.Drawable的gtk.gdk.Window。
我的问题:
答案 0 :(得分:11)
要理解的关键区别是gtk.gdk.Window
不是大多数人想到的意义上的“窗口”。它不是GUI元素,它只是屏幕的一部分,充当逻辑显示区域,如explained in the documentation。通过这种方式,它更像是一个低级别的对象。
gtk.Window
对象(传统的“窗口”)包含window
属性,该属性是gtk.gdk.Window
使用的gtk.Window
对象。它在窗口初始化时创建(在这种情况下,在调用win.show_all()
之后)。
以下是正确保存图像的代码修订版:
import gtk
import gobject
def main():
button = gtk.Button("Hello")
scroll_win = gtk.ScrolledWindow()
scroll_win.add(button)
win = gtk.Window(gtk.WINDOW_TOPLEVEL)
win.add(scroll_win)
win.show_all()
# Set timeout to allow time for the screen to be drawn
# before saving the window image
gobject.timeout_add(1000, drawWindow, win)
def drawWindow(win):
width, height = win.get_size()
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, width, height)
# Retrieve the pixel data from the gdk.window attribute (win.window)
# of the gtk.window object
screenshot = pixbuf.get_from_drawable(win.window, win.get_colormap(),
0, 0, 0, 0, width, height)
screenshot.save('screenshot.png', 'png')
# Return False to stop the repeating interval
return False
if __name__ == '__main__':
main()
gtk.main()
超时是必要的,因为即使已经创建了gtk.gdk.Window
对象,我仍然没有绘制屏幕,直到gtk.main()
开始运行,我想。如果您在win.show_all()
之后立即读取像素缓冲区,它将保存图像,但图像将是窗口稍后将占用的屏幕部分。如果您想亲自试用,只需拨打gobject.timeout_add
,即可将来电替换为drawWindow(win)
。
请注意,此方法保存GTK窗口的图像,但不保存窗口的边框(因此,没有标题栏)。
另外,作为一个侧点,在定义使用gobject.timeout_add
调用的函数时,您实际上不必显式使用return False
,它只需要计算等效于{的值{1}}。如果函数中没有0
语句,Python默认返回None
,因此该函数默认只调用一次。如果您希望在另一个间隔后再次调用该函数,请返回return
。
正如liberforce所指出的,更好的方法是连接到GTK用来传递事件(以及一般状态变化)的信号,而不是使用超时。
从True
继承的任何东西(基本上所有小部件都有)具有gobject.GObject
函数,该函数用于向给定信号注册回调。我尝试了一些信号,看起来我们想要使用的是connect()
,它发生在需要重绘小部件的任何时候(包括第一次绘制它)。因为我们希望在回调发生之前绘制窗口,所以我们将使用expose-event
变体。
以下是修订后的代码:
connect_after()