python - 如何强制屏幕截图大小比例。PyQt5
问题描述
我想从GitHub/harupy/snipping-tool修改 Screen-Snip 代码,使每个 screen-snip 的比例为 3 x 2。(稍后我将保存为 600 x 400 px 的图像)
我不确定如何 self.end
动态修改,以便用户以 3 x 2 的比例单击和拖动。鼠标位置将定义x
坐标,y
坐标将为int(x * 2/3)
关于如何做到这一点的任何建议?我保证我一直在研究这个,我似乎无法“破解代码”只修改y
坐标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 有多种方法,您使用两个点,另一种(更常见)是使用原点坐标和矩形大小。
一旦知道宽度,就可以计算高度,如果终点的 y 高于起点,则将其设为负数。
请注意,通过这种方式,您可以获得“负”矩形(负宽度,“右”边缘实际上在左侧,高度/底部相同),因此通常最好使用normalized
,这也可以让您获得用于屏幕抓取的矩形的正确坐标。
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 已经提供了所有必要的工具。
你可以使用类似的东西:
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)
推荐阅读
- discord - 如何让它滚动多次
- git - 无法使用 shell 运行 gitlab runner
- ansible - 从 kolla-ansible 中删除以前部署的服务的正确方法是什么
- javascript - 如何编写来自 Google 表单上传的照片并将其大小设置为 1 英寸以在模板中显示?
- apache-spark - Spark 会话未初始化 | sparkR.session() 给出错误“if (len > 0) { 中的错误:参数长度为零”
- javascript - 如果存在特定元素,有没有办法为同一个变量分配不同的值?
- probability - 如何确定有问题的概率百分比
- javascript - 在异步函数上调用之后如何获取异步函数的返回值
- php - 使用 ajax 调用的 shell_exec 在 inux 中不起作用
- python - 无法在树莓派上安装 PyQt5