如何强制屏幕截图大小比例.PyQt5 [英] How to force screen-snip size ratio. PyQt5

查看:94
本文介绍了如何强制屏幕截图大小比例.PyQt5的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想修改 GitHub/harupy/snipping-tool 以便每个屏幕截图的比例为 3 x 2.(稍后我将保存为 600 x 400 像素的图像)

I want to modify Screen-Snip code from GitHub/harupy/snipping-tool so that every screen-snip has a ratio of 3 x 2. (I will save as 600 x 400 px image later)

我不确定如何动态修改 self.end 以便用户以 3 x 2 的比例点击和拖动.鼠标位置将定义x坐标,y坐标为int(x * 2/3)

I'm not sure how to modify self.end dynamically so that the user clicks and drags with a 3 x 2 ratio. The mouse position will define the x coordinate, and the y coordinate will be int(x * 2/3)

关于如何做到这一点的任何建议?我保证我一直在研究这个,但我似乎无法破解密码".只修改self.end

Any suggestions on how to do this? I promise I've been researching this, and I just can't seem to "crack the code" of modifying only the y coordinate of self.end

代码如下:

import sys
import PyQt5
from PyQt5 import QtWidgets, QtCore, QtGui
import tkinter as tk
from PIL import ImageGrab
import numpy as np
import cv2 # package is officially called opencv-python


class MyWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        root = tk.Tk()
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        self.setGeometry(0, 0, screen_width, screen_height)
        self.setWindowTitle(' ')
        self.begin = QtCore.QPoint()
        self.end = QtCore.QPoint()
        self.setWindowOpacity(0.3)
        QtWidgets.QApplication.setOverrideCursor(
            QtGui.QCursor(QtCore.Qt.CrossCursor)
        )
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        print('Capture the screen...')
        self.show()

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setPen(QtGui.QPen(QtGui.QColor('black'), 3))
        qp.setBrush(QtGui.QColor(128, 128, 255, 128))
        qp.drawRect(QtCore.QRect(self.begin, self.end)) ##### This seems like the place I should modify. #########

    def mousePressEvent(self, event):
        self.begin = event.pos()
        self.end = self.begin
        self.update()

    def mouseMoveEvent(self, event):
        self.end = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        self.close()

        x1 = min(self.begin.x(), self.end.x())
        y1 = min(self.begin.y(), self.end.y())
        x2 = max(self.begin.x(), self.end.x())
        y2 = max(self.begin.y(), self.end.y())

        img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
        img.save('capture.png')
        img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)

        cv2.imshow('Captured Image', img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MyWidget()
    window.show()
    app.aboutToQuit.connect(app.deleteLater)
    sys.exit(app.exec_())

推荐答案

您不需要更改 y 坐标",您只需要使用正确的参数来创建矩形.初始化一个 QRect 的方法有很多种,你使用的是两点,另一种(更常见的)是使用原点的坐标和矩形的大小.

You don't need to "change the y coordinate", you just need to use the correct arguments to create the rectangle. There are various ways to initialize a QRect, you are using the two points, another one (and more common) is to use the coordinates of the origin and the size of the rectangle.

一旦知道宽度,就可以计算高度,如果终点的 y 高于起点,则将其设为负数.

Once you know the width, you can compute the height, and make it negative if the y of the end point is above the begin.

请注意,通过这种方式,您可能会得到否定"结果.矩形(负宽度,右"边实际上在左边,高度/底部相同),所以通常最好使用 normalized,它还允许您获取矩形的正确坐标以进行屏幕抓取.

Note that in this way you could get a "negative" rectangle (negative width, with the "right" edge actually at the left, the same for the height/bottom), so it's usually better to use normalized, which also allows you to get the correct coordinates of the rectangle for screen grabbing.

class MyWidget(QtWidgets.QWidget):
    # ...

    def getRect(self):
        # a commodity function that always return a correctly sized
        # rectangle, with normalized coordinates
        width = self.end.x() - self.begin.x()
        height = abs(width * 2 / 3)
        if self.end.y() < self.begin.y():
            height *= -1
        return QtCore.QRect(self.begin.x(), self.begin.y(), 
            width, height).normalized()

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setPen(QtGui.QPen(QtGui.QColor('black'), 3))
        qp.setBrush(QtGui.QColor(128, 128, 255, 128))
        qp.drawRect(self.getRect())

    def mouseReleaseEvent(self, event):
        self.close()

        rect = self.getRect()
        img = ImageGrab.grab(bbox=(
            rect.topLeft().x(), 
            rect.topLeft().y(), 
            rect.bottomRight().x(), 
            rect.bottomRight().y()
        ))

        # ...

我建议您像在某些系统(特别是 Linux)中那样使用延迟 setGeometry,最终"只有当窗口从窗口管理器正确映射时才实际应用几何图形,特别是如果窗口管理器倾向于在第一次显示窗口时自行应用几何图形.例如,我有两个屏幕,而你的窗口居中"了.在我的主屏幕上,使其移动另一个屏幕的一半宽度.还要考虑为屏幕尺寸导入 Tk 没有多大意义,因为 Qt 已经提供了所有必要的工具.

I suggest you to use a delayed setGeometry as in some systems (specifically Linux), the "final" geometry is actually applied only as soon as the window is correctly mapped from the window manager, especially if the window manager tends to apply a geometry on its own when the window is shown the first time. For example, I have two screens, and your window got "centered" on my main screen, making it shifted by half width of the other screen. Also consider that importing Tk just for the screen size doesn't make much sense, since Qt already provides all necessary tools.

你可以使用类似的东西:

You can use something like that:

class MyWidget(QtWidgets.QWidget):
    # ...

    def showEvent(self, event):
        if not event.spontaneous():
            # delay the geometry on the "next" cycle of the Qt event loop;
            # this should take care of positioning issues for systems that
            # try to move newly created windows on their own
            QtCore.QTimer.singleShot(0, self.resetPos)

    def resetPos(self):
        rect = QtCore.QRect()
        # create a rectangle that is the sum of the geometries of all available
        # screens; the |= operator acts as `rect = rect.united(screen.geometry())`
        for screen in QtWidgets.QApplication.screens():
            rect |= screen.geometry()
        self.setGeometry(rect)

这篇关于如何强制屏幕截图大小比例.PyQt5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆