最近心血来潮,就想自己写一个截图的小工具,使用PyQt5实现一个简易的截图工具,按下快捷键就可以进行截图
需要安装的包:
pip install PyQt5
pip install keyboard
1、 初始化窗口,设置鼠标监听,设置十字光标,还有就是设置窗口无边框和窗口全屏。
def initWindow(self):
self.setMouseTracking(True) # 鼠标追踪
self.setCursor(Qt.CrossCursor) # 设置光标
self.setWindowFlag(Qt.FramelessWindowHint) # 窗口无边框
self.setWindowState(Qt.WindowFullScreen) # 窗口全屏
2、 获取全屏的图片。
def captureFullScreen(self):
self.fullScreenImage = QGuiApplication.primaryScreen().grabWindow(QApplication.desktop().winId())
3、 填充步骤一获取到的全屏图片到窗口, 并重写paintEvent事件, 使用QPainter来绘制全屏的图片到窗口。
def paintBackgroundImage(self):
shadowColor = QColor(0, 0, 0, 100) # 黑色半透明
self.painter.drawPixmap(0, 0, self.fullScreenImage)
self.painter.fillRect(self.fullScreenImage.rect(), shadowColor) # 填充矩形阴影
def paintEvent(self, event):
self.painter.begin(self) # 开始重绘
self.paintBackgroundImage()
penColor = QColor(30, 144, 245) # 画笔颜色
self.painter.setPen(QPen(penColor, 1, Qt.SolidLine, Qt.RoundCap)) # 设置画笔,蓝色,1px大小,实线,圆形笔帽
if self.isMousePressLeft is True:
pickRect = self.getRectangle(self.beginPosition, self.endPosition) # 获得要截图的矩形框
self.captureImage = self.fullScreenImage.copy(pickRect) # 捕获截图矩形框内的图片
self.painter.drawPixmap(pickRect.topLeft(), self.captureImage) # 填充截图的图片
self.painter.drawRect(pickRect) # 画矩形边框
self.painter.end() # 结束重绘
4、 完善步骤三中使用到的getRectangle()函数,意思时鼠标选取需要截取的区域, 利用paintEvent在窗口上显示出来。
def getRectangle(self, beginPoint, endPoint):
pickRectWidth = int(qAbs(beginPoint.x() - endPoint.x()))
pickRectHeight = int(qAbs(beginPoint.y() - endPoint.y()))
pickRectTop = beginPoint.x() if beginPoint.x() < endPoint.x() else endPoint.x()
pickRectLeft = beginPoint.y() if beginPoint.y() < endPoint.y() else endPoint.y()
pickRect = QRect(pickRectTop, pickRectLeft, pickRectWidth, pickRectHeight)
# 避免高度宽度为0时候报错
if pickRectWidth == 0:
pickRect.setWidth(2)
if pickRectHeight == 0:
pickRect.setHeight(2)
return pickRect
5、 重写鼠标和键盘事件,鼠标左键点击开始记录坐标,鼠标左键释放记录结束的坐标,传递给paintEvent中的getRectangle(),开始坐标和结束坐标形成的矩形就是我们需要截图的区域,鼠标双击或者按Enter都可以保存图片,如果开始截图了,没有选取,按一次右键直接退出截图(或者按ESC也可以),如果选取了要截图的区域,按一次右键重新开始截图,类似于QQ截图。
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.beginPosition = event.pos() # 记录选取区域开始的坐标
self.isMousePressLeft = True
if event.button() == Qt.RightButton:
# 如果选取了图片,则按一次右键开始重新截图
if self.captureImage is not None:
self.captureImage = None
self.paintBackgroundImage()
self.update() # update的作用是调用paintEvent
else:
self.close() # 关闭窗口
def mouseMoveEvent(self, event):
if self.isMousePressLeft is True:
self.endPosition = event.pos() # 选取区域结束坐标
self.update()
def mouseReleaseEvent(self, event):
self.endPosition = event.pos() #记录选取区域结束的坐标
self.isMousePressLeft = False
def mouseDoubleClickEvent(self, event):
if self.captureImage is not None:
self.saveImage() # 保存截图图片
self.close() # 关闭窗口
def keyPressEvent(self, event):
if event.key() == Qt.Key_Escape:
self.close() # 关闭窗口
if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
if self.captureImage is not None:
self.saveImage() # 保存截图图片
self.close() # 关闭窗口
6、 保存图片
def saveImage(self):
self.captureImage.save('picture.png') # 保存图片到当前文件夹中
import sys
import keyboard
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt, qAbs, QRect
from PyQt5.QtGui import QPen, QPainter, QColor, QGuiApplication
class CaptureScreen(QWidget):
# 初始化变量
beginPosition = None
endPosition = None
fullScreenImage = None
captureImage = None
isMousePressLeft = None
painter = QPainter()
def __init__(self):
super(QWidget, self).__init__()
self.initWindow() # 初始化窗口
self.captureFullScreen() # 获取全屏
def initWindow(self):
self.setMouseTracking(True) # 鼠标追踪
self.setCursor(Qt.CrossCursor) # 设置光标
self.setWindowFlag(Qt.FramelessWindowHint) # 窗口无边框
self.setWindowState(Qt.WindowFullScreen) # 窗口全屏
def captureFullScreen(self):
self.fullScreenImage = QGuiApplication.primaryScreen().grabWindow(QApplication.desktop().winId())
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.beginPosition = event.pos()
self.isMousePressLeft = True
if event.button() == Qt.RightButton:
# 如果选取了图片,则按一次右键开始重新截图
if self.captureImage is not None:
self.captureImage = None
self.paintBackgroundImage()
self.update()
else:
self.close()
def mouseMoveEvent(self, event):
if self.isMousePressLeft is True:
self.endPosition = event.pos()
self.update()
def mouseReleaseEvent(self, event):
self.endPosition = event.pos()
self.isMousePressLeft = False
def mouseDoubleClickEvent(self, event):
if self.captureImage is not None:
self.saveImage()
self.close()
def keyPressEvent(self, event):
if event.key() == Qt.Key_Escape:
self.close()
if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
if self.captureImage is not None:
self.saveImage()
self.close()
def paintBackgroundImage(self):
shadowColor = QColor(0, 0, 0, 100) # 黑色半透明
self.painter.drawPixmap(0, 0, self.fullScreenImage)
self.painter.fillRect(self.fullScreenImage.rect(), shadowColor) # 填充矩形阴影
def paintEvent(self, event):
self.painter.begin(self) # 开始重绘
self.paintBackgroundImage()
penColor = QColor(30, 144, 245) # 画笔颜色
self.painter.setPen(QPen(penColor, 1, Qt.SolidLine, Qt.RoundCap)) # 设置画笔,蓝色,1px大小,实线,圆形笔帽
if self.isMousePressLeft is True:
pickRect = self.getRectangle(self.beginPosition, self.endPosition) # 获得要截图的矩形框
self.captureImage = self.fullScreenImage.copy(pickRect) # 捕获截图矩形框内的图片
self.painter.drawPixmap(pickRect.topLeft(), self.captureImage) # 填充截图的图片
self.painter.drawRect(pickRect) # 画矩形边框
self.painter.end() # 结束重绘
def getRectangle(self, beginPoint, endPoint):
pickRectWidth = int(qAbs(beginPoint.x() - endPoint.x()))
pickRectHeight = int(qAbs(beginPoint.y() - endPoint.y()))
pickRectTop = beginPoint.x() if beginPoint.x() < endPoint.x() else endPoint.x()
pickRectLeft = beginPoint.y() if beginPoint.y() < endPoint.y() else endPoint.y()
pickRect = QRect(pickRectTop, pickRectLeft, pickRectWidth, pickRectHeight)
# 避免高度宽度为0时候报错
if pickRectWidth == 0:
pickRect.setWidth(2)
if pickRectHeight == 0:
pickRect.setHeight(2)
return pickRect
def saveImage(self):
self.captureImage.save('picture.png', quality=95) # 保存图片到当前文件夹中
if __name__ == "__main__":
keyboard.wait(hotkey='f4') # 按F4开始截图
app = QApplication(sys.argv)
windows = CaptureScreen()
windows.show()
sys.exit(app.exec_())