wxPython:绘制在GenStaticBitmap的顶部



我想截取我的显示器的屏幕截图,并通过点击和拖动鼠标在其上画一个框。为了监听鼠标事件,我使用wx.lib.statbmp中的GenStaticBitmap,而不仅仅是StaticBitmap。这是目前为止我为"绘图窗口"编写的代码类:

def __init__(self, parent = None, id=wx.ID_ANY):
wx.Frame.__init__(self, parent, id, size = wx.DisplaySize())
#Grab a screenshot and create GenStaticBitmap with it
with mss() as sct:
monitor = sct.monitors[1]
img = sct.grab(monitor)
width, height = img.size
img = Image.frombytes("RGB", img.size, img.bgra, "raw", "BGRX")
img = wx.Bitmap.FromBuffer(width, height, img.tobytes())
self.bmp = wxbmp.GenStaticBitmap(self, ID=wx.ID_ANY, bitmap=img)
self.bmp.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_click)
self.bmp.Bind(wx.EVT_MOTION, self.on_move)
self.bmp.Bind(wx.EVT_LEFT_UP, self.exit)
self.bmp.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_KEY_DOWN, self.exit)
self.ShowFullScreen(True)
self.SetCursor(wx.Cursor(wx.CURSOR_CROSS))
def OnPaint(self, event):
if self.p1 is None or self.p2 is None: 
return
dc = wx.PaintDC(self.bmp)
dc.SetPen(wx.Pen('red', 1))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawRectangle(self.p1.x, self.p1.y, self.p2.x - self.p1.x, self.p2.y - self.p1.y)
def on_mouse_click(self, event):
self.p1 = event.GetPosition()
def on_move(self, event):
if event.Dragging() and event.LeftIsDown():
self.p2 = event.GetPosition()
self.bmp.Refresh()
def exit(self, event):
self.Destroy()

改编自《如何使用wxPython在透明背景上拖动鼠标来选择要捕获的屏幕矩形》。

问题是,绘制到屏幕上的每个矩形仍然落后于当前矩形,在矩形的填充似乎是黑色而不是透明的事实之上。如果我做dc.Clear(),那修复了绘图,但去掉了底层的位图。如果我只是画一个没有位图的帧,这个代码工作得很好。我试过使用wx.MemoryDC([my bitmap]),在那里绘图,然后在OnPaint()中做self.bmp.SetBitmap([my bitmap]),但这似乎根本不起作用。任何建议都是感激的!

非常感谢Igor。以下是新的"绘图窗口"类,它似乎运行良好。

def __init__(self, parent=None, id=wx.ID_ANY):
wx.Frame.__init__(self, parent, id, size=wx.DisplaySize())
#Grab a screenshot and create GenStaticBitmap with it
with mss() as sct:
monitor = sct.monitors[1]
img = sct.grab(monitor)
width, height = img.size
img = Image.frombytes("RGB", img.size, img.bgra, "raw", "BGRX")
img = wx.Bitmap.FromBuffer(width, height, img.tobytes())
self.bmp = wxbmp.GenStaticBitmap(self, ID=wx.ID_ANY, bitmap=img)
self.overlay = wx.Overlay()
self.bmp.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_click)
self.bmp.Bind(wx.EVT_MOTION, self.on_move)
self.bmp.Bind(wx.EVT_LEFT_UP, self.exit)
self.Bind(wx.EVT_KEY_DOWN, self.exit)
self.ShowFullScreen(True)
self.SetCursor(wx.Cursor(wx.CURSOR_CROSS))
def on_mouse_click(self, event):
self.p1 = event.GetPosition()
def on_move(self, event):
if event.Dragging() and event.LeftIsDown():
self.p2 = event.GetPosition()

dc = wx.ClientDC(self.bmp)
odc = wx.DCOverlay(self.overlay, dc)
odc.Clear()
dc.SetPen(wx.Pen('red', 1))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawRectangle(self.p1.x, self.p1.y, self.p2.x - self.p1.x, self.p2.y - self.p1.y)

def exit(self, event):
self.Destroy()

最新更新