我在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)。很奇怪,我会在他们的存储库中报告这个问题。
答案 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()