如何使用wxPython select 通过在透明背景上拖动鼠标来捕获屏幕的矩形?
How to select a rectangle of the screen to capture by dragging mouse on transparent background with wxPython?
我正在构建一个使用 ffmpeg 捕获屏幕的应用程序,我想通过拖动鼠标、绘制矩形并将参数传递给 ffmpeg 调用来确定要捕获的屏幕部分。
我正在使用 wxPython 为应用程序构建一个简单的 GUI。我已经到了可以绘制矩形并获得所需坐标的地步:所选区域的偏移量和大小。
import wx
global selectionOffset, selectionSize
selectionOffset = ""
selectionSize = ""
class SelectableFrame(wx.Frame):
c1 = None
c2 = None
def __init__(self, parent=None, id=wx.ID_ANY, title=""):
wx.Frame.__init__(self, parent, id, title, size=wx.DisplaySize(), style=wx.TRANSPARENT_WINDOW)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetCursor(wx.Cursor(wx.CURSOR_CROSS))
def OnMouseMove(self, event):
if event.Dragging() and event.LeftIsDown():
self.c2 = event.GetPosition()
self.Refresh()
def OnMouseDown(self, event):
self.c1 = event.GetPosition()
def OnMouseUp(self, event):
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
self.Destroy()
def OnPaint(self, event):
global selectionOffset, selectionSize
if self.c1 is None or self.c2 is None: return
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('red', 1))
dc.SetBrush(wx.Brush(wx.Colour(0, 0, 0), wx.TRANSPARENT))
dc.DrawRectangle(self.c1.x, self.c1.y, self.c2.x - self.c1.x, self.c2.y - self.c1.y)
selectionOffset = str(self.c1.x) + "x" + str(self.c1.y)
selectionSize = str(abs(self.c2.x - self.c1.x)) + "x" + str(abs(self.c2.y - self.c1.y))
def PrintPosition(self, pos):
return str(pos.x) + "x" + str(pos.y)
class MyApp(wx.App):
def OnInit(self):
frame = SelectableFrame()
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(redirect=False)
app.MainLoop()
print("offset: " + selectionOffset + ". Screen selection size: " + selectionSize)
问题是我无法让 "background" 透明,所以我可以看到我真正抓住的是屏幕的哪一部分。我怎样才能用 wxPython 做到这一点?如果使用其他 GUI 工具或 python 模块有更简单的方法,我愿意接受建议。谢谢!
我一直不清楚这是为什么,但您必须先允许 window 到 "setup",然后才能访问透明度选项。
在下文中,我包含了一个菜单选项来打开和关闭透明度(0 是完全透明的,255 是完全不透明的)。
我还包括了一个 wx.CallLater
来设置启动时的透明度。
import wx
global selectionOffset, selectionSize
selectionOffset = ""
selectionSize = ""
class SelectableFrame(wx.Frame):
c1 = None
c2 = None
def __init__(self, parent=None, id=wx.ID_ANY, title=""):
wx.Frame.__init__(self, parent, id, title, size=wx.DisplaySize())
self.menubar = wx.MenuBar(wx.MB_DOCKABLE)
self.filem = wx.Menu()
self.filem.Append(wx.ID_EXIT, '&Transparency')
self.menubar.Append(self.filem, '&File')
self.SetMenuBar(self.menubar)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_MENU, self.OnTrans)
self.SetCursor(wx.Cursor(wx.CURSOR_CROSS))
self.Show()
self.transp = False
wx.CallLater(250, self.OnTrans, None)
def OnTrans(self, event):
if self.transp == False:
self.SetTransparent(180)
self.transp = True
else:
self.SetTransparent(255)
self.transp = False
def OnMouseMove(self, event):
if event.Dragging() and event.LeftIsDown():
self.c2 = event.GetPosition()
self.Refresh()
def OnMouseDown(self, event):
self.c1 = event.GetPosition()
def OnMouseUp(self, event):
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
self.Destroy()
def OnPaint(self, event):
global selectionOffset, selectionSize
if self.c1 is None or self.c2 is None: return
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('red', 1))
dc.SetBrush(wx.Brush(wx.Colour(0, 0, 0), wx.TRANSPARENT))
dc.DrawRectangle(self.c1.x, self.c1.y, self.c2.x - self.c1.x, self.c2.y - self.c1.y)
selectionOffset = str(self.c1.x) + "x" + str(self.c1.y)
selectionSize = str(abs(self.c2.x - self.c1.x)) + "x" + str(abs(self.c2.y - self.c1.y))
def PrintPosition(self, pos):
return str(pos.x) + "x" + str(pos.y)
class MyApp(wx.App):
def OnInit(self):
frame = SelectableFrame()
return True
app = MyApp(redirect=False)
app.MainLoop()
print("offset: " + selectionOffset + ". Screen selection size: " + selectionSize)
我正在构建一个使用 ffmpeg 捕获屏幕的应用程序,我想通过拖动鼠标、绘制矩形并将参数传递给 ffmpeg 调用来确定要捕获的屏幕部分。
我正在使用 wxPython 为应用程序构建一个简单的 GUI。我已经到了可以绘制矩形并获得所需坐标的地步:所选区域的偏移量和大小。
import wx
global selectionOffset, selectionSize
selectionOffset = ""
selectionSize = ""
class SelectableFrame(wx.Frame):
c1 = None
c2 = None
def __init__(self, parent=None, id=wx.ID_ANY, title=""):
wx.Frame.__init__(self, parent, id, title, size=wx.DisplaySize(), style=wx.TRANSPARENT_WINDOW)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetCursor(wx.Cursor(wx.CURSOR_CROSS))
def OnMouseMove(self, event):
if event.Dragging() and event.LeftIsDown():
self.c2 = event.GetPosition()
self.Refresh()
def OnMouseDown(self, event):
self.c1 = event.GetPosition()
def OnMouseUp(self, event):
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
self.Destroy()
def OnPaint(self, event):
global selectionOffset, selectionSize
if self.c1 is None or self.c2 is None: return
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('red', 1))
dc.SetBrush(wx.Brush(wx.Colour(0, 0, 0), wx.TRANSPARENT))
dc.DrawRectangle(self.c1.x, self.c1.y, self.c2.x - self.c1.x, self.c2.y - self.c1.y)
selectionOffset = str(self.c1.x) + "x" + str(self.c1.y)
selectionSize = str(abs(self.c2.x - self.c1.x)) + "x" + str(abs(self.c2.y - self.c1.y))
def PrintPosition(self, pos):
return str(pos.x) + "x" + str(pos.y)
class MyApp(wx.App):
def OnInit(self):
frame = SelectableFrame()
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(redirect=False)
app.MainLoop()
print("offset: " + selectionOffset + ". Screen selection size: " + selectionSize)
问题是我无法让 "background" 透明,所以我可以看到我真正抓住的是屏幕的哪一部分。我怎样才能用 wxPython 做到这一点?如果使用其他 GUI 工具或 python 模块有更简单的方法,我愿意接受建议。谢谢!
我一直不清楚这是为什么,但您必须先允许 window 到 "setup",然后才能访问透明度选项。
在下文中,我包含了一个菜单选项来打开和关闭透明度(0 是完全透明的,255 是完全不透明的)。
我还包括了一个 wx.CallLater
来设置启动时的透明度。
import wx
global selectionOffset, selectionSize
selectionOffset = ""
selectionSize = ""
class SelectableFrame(wx.Frame):
c1 = None
c2 = None
def __init__(self, parent=None, id=wx.ID_ANY, title=""):
wx.Frame.__init__(self, parent, id, title, size=wx.DisplaySize())
self.menubar = wx.MenuBar(wx.MB_DOCKABLE)
self.filem = wx.Menu()
self.filem.Append(wx.ID_EXIT, '&Transparency')
self.menubar.Append(self.filem, '&File')
self.SetMenuBar(self.menubar)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_MENU, self.OnTrans)
self.SetCursor(wx.Cursor(wx.CURSOR_CROSS))
self.Show()
self.transp = False
wx.CallLater(250, self.OnTrans, None)
def OnTrans(self, event):
if self.transp == False:
self.SetTransparent(180)
self.transp = True
else:
self.SetTransparent(255)
self.transp = False
def OnMouseMove(self, event):
if event.Dragging() and event.LeftIsDown():
self.c2 = event.GetPosition()
self.Refresh()
def OnMouseDown(self, event):
self.c1 = event.GetPosition()
def OnMouseUp(self, event):
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
self.Destroy()
def OnPaint(self, event):
global selectionOffset, selectionSize
if self.c1 is None or self.c2 is None: return
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('red', 1))
dc.SetBrush(wx.Brush(wx.Colour(0, 0, 0), wx.TRANSPARENT))
dc.DrawRectangle(self.c1.x, self.c1.y, self.c2.x - self.c1.x, self.c2.y - self.c1.y)
selectionOffset = str(self.c1.x) + "x" + str(self.c1.y)
selectionSize = str(abs(self.c2.x - self.c1.x)) + "x" + str(abs(self.c2.y - self.c1.y))
def PrintPosition(self, pos):
return str(pos.x) + "x" + str(pos.y)
class MyApp(wx.App):
def OnInit(self):
frame = SelectableFrame()
return True
app = MyApp(redirect=False)
app.MainLoop()
print("offset: " + selectionOffset + ". Screen selection size: " + selectionSize)