使用ScreenDC,wxPython的多个屏幕截图

时间:2017-03-23 18:53:25

标签: python wxpython wxwidgets

我在wxPython Phoenix中遇到了ScreenDC的问题。

我的工具应该在一段时间内拍摄多个屏幕截图。但每当我使用ScreenDC抓取屏幕截图并将其保存到PNG时,它只能在第一次运行良好。以下所有时间它只保存与第一个相同的图像。要获得新图像,我必须重新启动程序,这在我的情况下不是一个选项。我想每当我打电话给wx.ScreenDC()时,它就会得到与第一次相同的图像。

Ubuntu 16.04,wxPython 3.0.3 gtk3,python 3.6

我使用的代码:

def take_screenshot():
    screen = wx.ScreenDC()
    size = screen.GetSize()
    width = size[0]
    height = size[1]
    bmp = wx.Bitmap(width, height)
    mem = wx.MemoryDC(bmp)
    mem.Blit(0, 0, width, height, screen, 0, 0)
    bmp.SaveFile(str(datetime.now()) + '.png', wx.BITMAP_TYPE_PNG)

if __name__ == '__main__':
    app = wx.App()
    take_screenshot()
    sleep(3)
    take_screenshot()
    sleep(3)
    take_screenshot()
    sleep(3)
    take_screenshot()

也许有办法从记忆中清除第一张图片。

我发现的唯一解决方案是运行一个单独的进程,在内部定义wx.App然后执行该功能。但是,这不是我的计划的选择。

感谢。

UPD :这似乎是wxPython Phoenix的一些问题。如果你在wxPython Classic上运行它,一切正常(只使用EmptyBitmap,而不是Bitmap)。很奇怪,我会在他们的存储库中报告这个问题。

1 个答案:

答案 0 :(得分:0)

我无法在Phoenix或Classic中重现您的问题(在Windows上)。我想可能发生的是sleep阻塞wxPython事件循环。无论如何,将长时间运行的东西放在一个单独的线程中是一种很好的方式。它是无痛的,见下文。

from threading import Thread

...

if __name__ == '__main__':
    app = wx.App()
    def payload():
        take_screenshot()
        sleep(3)
        take_screenshot()
        sleep(3)
        take_screenshot()
        sleep(3)
        take_screenshot()
    thrd = Thread(target=payload)
    thrd.start()
编辑:正如提问者指出的那样,上述方法可能存在线程安全问题。这件事情如何适用于你(在Windows上的Phoenix和Classic上测试过)?

from __future__ import print_function

import wx
from datetime import datetime
from time import sleep

IS_PHOENIX = True if 'phoenix' in wx.version() else False

if IS_PHOENIX:
    EmptyBitmap = lambda *args, **kwds: wx.Bitmap(*args, **kwds)
else:
    EmptyBitmap = lambda *args, **kwds: wx.EmptyBitmap(*args, **kwds)

def take_screenshot():
    screen = wx.ScreenDC()
    size = screen.GetSize()
    width = size[0]
    height = size[1]
    bmp = EmptyBitmap(width, height)
    mem = wx.MemoryDC(bmp)
    mem.Blit(0, 0, width, height, screen, 0, 0)
    bmp.SaveFile(str(datetime.now().second) + '.png', wx.BITMAP_TYPE_PNG)

MAXPICS = 4

class testfrm(wx.Frame):
    def __init__(self, *args, **kwds):
        wx.Frame.__init__(self, *args, **kwds)
        self.tmr = wx.Timer(self, -1)
        self.countpics = 0
        self.Bind(wx.EVT_TIMER, self.ontimer, self.tmr)
        self.ontimer(None)

    def ontimer(self, evt):
        if self.countpics <=MAXPICS:
            self.tmr.Start(3000, wx.TIMER_ONE_SHOT)
            take_screenshot()
            self.countpics += 1
        else:
            self.Close()


if __name__ == '__main__':
    app = wx.App()
    frm = testfrm(None, -1, wx.version())
    app.MainLoop()