简体   繁体   English

使用Wx和PyAutoGui从Python制作“剪裁工具”

[英]Making “Snipping Tool” from Python using Wx and PyAutoGui

I am trying to make a snipping tool using the Wx and PyAutoGui modules, I am stuck at a certain problem: The saved image file is at wrong position (see image below) 我正在尝试使用Wx和PyAutoGui模块制作剪裁工具,但遇到了以下问题:保存的图像文件位置错误(请参见下图)

Picture Link 图片链接

As you can see I am trying to grab a specific region, that is the red rectangle, and save those pixels in that region to the file "my_screenshot.png". 如您所见,我正在尝试获取一个特定区域,即红色矩形,并将该区域中的那些像素保存到文件“ my_screenshot.png”中。 However, the position/coordinates seems to be off (you can see the rectangles, which was supposed to be the region of the screenshot) 但是,位置/坐标似乎已关闭(您可以看到矩形,该矩形应该是屏幕截图的区域)

Here are the codes: 以下是代码:

import wx
import pyautogui

class SelectableFrame(wx.Frame):

    c1 = None
    c2 = None

    def __init__(self, parent=None, id=-1, title=""):
        wx.Frame.__init__(self, parent, id, title, size=wx.DisplaySize())

        self.panel = wx.Panel(self, size=self.GetSize())

        self.panel.Bind(wx.EVT_MOTION, self.OnMouseMove)
        self.panel.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
        self.panel.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
        self.panel.Bind(wx.EVT_PAINT, self.OnPaint)

        self.SetCursor(wx.Cursor(wx.CURSOR_CROSS))

        self.SetTransparent(50)

    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))
        region = (self.c1.x, self.c1.y, self.c2.x - self.c1.x, self.c2.y - self.c1.y)
        pyautogui.screenshot('my_screenshot.png', region=region)
        print("MouseUp: " + str(region))
        self.Hide()

    def OnPaint(self, event):
        if self.c1 is None or self.c2 is None: return

        dc = wx.PaintDC(self.panel)
        dc.SetPen(wx.Pen('red', 1))
        dc.SetBrush(wx.Brush(wx.Colour(0, 0, 0), wx.TRANSPARENT))

        region = (self.c1.x, self.c1.y, self.c2.x - self.c1.x, self.c2.y - self.c1.y)
        dc.DrawRectangle(self.c1.x, self.c1.y, self.c2.x - self.c1.x, self.c2.y - self.c1.y)
        print("Draw: " + str(region))


    def PrintPosition(self, pos):
        return str(pos.x) + " " + str(pos.y)


class MyApp(wx.App):

    def OnInit(self):
        frame = SelectableFrame()
        frame.Show(True)
        self.SetTopWindow(frame)

        return True


app = MyApp(0)
app.MainLoop()

From what I've gathered that, it took the width and height, but wrong x and y position, how can I fix that? 从我收集到的信息来看,它采用了宽度和高度,但是x和y位置错误,我该如何解决? Thank you 谢谢

EDIT: There seems to be values difference between these functions 编辑:这些函数之间似乎存在值差异

    def OnMouseDown(self, event):
        self.c1 = event.GetPosition()
        print("MouseDown[event]: " + str(self.c1))
        print("MouseDown[gui]: "+  str(pyautogui.position()))

Output: 输出:

MouseDown[event]: (729, 484)
MouseDown[gui]: Point(x=737, y=515)

The offset is +8 for x, and +31 for y. x的偏移量是+ 8,y的偏移量是+31。 How did this incontinence happen? 这种尿失禁是怎么发生的? My hotfix would be to add those offsets to the pyautogui.screenshot command but I don't think that is the right fix and would not be guaranteed to be the same offset values for other screen sizes.. 我的修复程序是将这些偏移量添加到pyautogui.screenshot命令中,但我认为这不是正确的解决方法,因此不能保证其他屏幕尺寸的偏移量都相同。

The wxpython MouseEvent doc tells wxpython MouseEvent文档告诉

The position associated with a mouse event is expressed in the window coordinates of the window which generated the event, you can use wx.Window.ClientToScreen to convert it to screen coordinates and possibly call wx.Window.ScreenToClient next to convert it to window coordinates of another window. 与鼠标事件关联的位置在生成事件的窗口的窗口坐标中表示,您可以使用wx.Window.ClientToScreen将其转换为屏幕坐标,还可以调用wx.Window.ScreenToClient将其转换为窗口坐标另一个窗口

pyautogui' screenshot() works with screen coordinates . pyautogui的screenshot()屏幕坐标配合使用

So, use wx.Window.ClientToScreen with both your c1 and c2 . 因此,将wx.Window.ClientToScreenc1c2

BTW, you should update c2 also at OnMouseUp and check it not to be 'None' nor equal to c1 . 顺便说一句,您还应该在OnMouseUp更新c2 ,并检查它是否不是'None'也不等于c1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM