python - 如何使用wxPython通过在透明背景上拖动鼠标来选择要捕获的屏幕矩形?

标签 python ffmpeg 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)

问题是我无法让“背景”变得透明,这样我就可以看到我真正捕获了屏幕的哪一部分。我怎样才能用 wxPython 做到这一点?如果有更简单的方法使用其他 GUI 工具或 python 模块,我愿意接受建议。谢谢!

最佳答案

我一直不清楚为什么会这样,但您必须先允许窗口“设置”,然后才能访问透明度选项。
在下面,我添加了一个菜单选项来打开和关闭透明度(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)

enter image description here

关于python - 如何使用wxPython通过在透明背景上拖动鼠标来选择要捕获的屏幕矩形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57342753/

相关文章:

python - 将 scikit-learn (sklearn) 预测添加到 pandas 数据框

python - Pandas - 你可以在跳过行的同时有条件地回填另一列吗?

c - 如何解释 ffmpeg AVERROR

linux - Linux下virtualenv安装wxPython

python - 将纬度/经度坐标列表转换为公司名称

python - 调用 python 脚本并在网页上填充结果

audio - 如何从 PureTool/CVS 视频转换音频流?

c++, ffmpeg 转码 : time_base differs depending on the container

python - 如何向 ObjectListView wxPython 添加仪表或进度条?

python - Py2exe lxml 问题