屏幕截图程序 - 透明截图区域 [英] Screen Snipping Program - Transparent Snipping Area

查看:74
本文介绍了屏幕截图程序 - 透明截图区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将我成功的屏幕截图程序从 Tkinter 转换为 PYQT5.我的问题是如何创建一个完全透明的剪切区域(动态更新的方形区域会很好).广场的外部将是半透明的.我已经查看了堆栈溢出和互联网,但找不到这样的示例(其他不是完全透明的绘图窗口).我附上了我的代码和我正在寻找的图片示例.SnippingWidget"是执行剪切逻辑的类.

I'm in the process of converting my successful screen snipping program from Tkinter to PYQT5. My question is how to create a fully transparent snipping area (a dynamically updating square region would be nice). The outside of the square will be semi-opaque. I've looked all over stack overflow and the internet and could not find an example of this (others are not a fully transparent drawing window). I've attached my code and a picture example of what I am looking for. The "SnippingWidget" is the class that does the snipping logic.

import sys

from PyQt5 import QtCore, QtGui
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction, QWidget
from PyQt5.QtGui import QIcon, QKeySequence
from PIL import ImageGrab

class App(QMainWindow):
    def __init__(self):
        super().__init__()

        self.initUI()
        self.topMenu()

    def initUI(self):

        self.setWindowTitle('Lil Snippy')
        self.setWindowIcon(QIcon('assets/lilSnippyIcon.png'))
        self.setGeometry(400, 300, 400, 300)
        self.show()

    def topMenu(self):
        menubar = self.menuBar()

        fileMenu = menubar.addMenu('File')
        saveAct = QAction(QIcon('assets/saveIcon.png'), 'Save', self)
        saveAsAct = QAction(QIcon('assets/saveAsIcon.png'), 'Save As', self)


        modeMenu = menubar.addMenu('Mode')
        snipAct = QAction(QIcon('assets/cameraIcon.png'), 'Snip', self)
        snipAct.setShortcut(QKeySequence('F1'))
        snipAct.triggered.connect(self.activateSnipping)
        videoAct = QAction(QIcon('assets/videoIcon.png'), 'Video', self)
        videoAct.setShortcut('F2')
        soundAct = QAction(QIcon('assets/audioIcon.png'), 'Sound', self)
        soundAct.setShortcut('F3')
        autoAct = QAction(QIcon('assets/automationIcon.png'), 'Automation', self)
        autoAct.setShortcut('F4')

        helpMenu = menubar.addMenu('Help')
        helpAct = QAction(QIcon('assets/helpIcon.png'), 'Help', self)
        aboutAct = QAction(QIcon('assets/aboutIcon.png'), 'About', self)

        fileMenu.addAction(saveAct)
        fileMenu.addAction(saveAsAct)
        modeMenu.addAction(snipAct)
        modeMenu.addAction(videoAct)
        modeMenu.addAction(soundAct)
        modeMenu.addAction(autoAct)
        helpMenu.addAction(helpAct)
        helpMenu.addAction(aboutAct)

    def activateSnipping(self):
        print("yes")
        self.Snipper = SnippingWidget()
        application.hide()

class SnippingWidget(QMainWindow):
    def __init__(self, parent = None):
        super(SnippingWidget, self).__init__(parent)
        self.setStyleSheet("background-color: transparent;")
        self.setWindowOpacity(.2)
        self.showFullScreen()

        self.outsideSquareColor = 'red'
        self.squareThickness = 4

        self.startX = None
        self.startY = None
        self.endX = None
        self.endY = None
        self.begin = QtCore.QPoint()
        self.end = QtCore.QPoint()

    def mousePressEvent(self, event):
        self.begin = event.pos()
        self.end = self.begin
        self.startX = event.x()
        self.startY = event.y()
        self.update()

    def mouseReleaseEvent(self, QMouseEvent):
        self.destroy()
        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('snips/testImage.png')
        application.show()

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

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setPen(QtGui.QPen(QtGui.QColor('red'), self.squareThickness))
        trans = QtGui.QColor(255,255,255,255)
        qp.setBrush(trans)
        rect = QtCore.QRectF(self.begin, self.end)
        qp.drawRect(rect)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    application = App()
    sys.exit(app.exec_())

推荐答案

你必须使用 QPainterPath 从窗口中减去选中矩形的矩形:

You have to use QPainterPath to subtract the rectangle from the window with the selected rectangle:

import sys

from PyQt5 import QtCore, QtGui, QtWidgets

from PIL import ImageGrab


class App(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        self.initUI()
        self.topMenu()

    def initUI(self):
        self.setWindowTitle("Lil Snippy")
        self.setWindowIcon(QtGui.QIcon("assets/lilSnippyIcon.png"))
        self.setGeometry(400, 300, 400, 300)

    def topMenu(self):
        menubar = self.menuBar()

        fileMenu = menubar.addMenu("File")
        saveAct = QtWidgets.QAction(QtGui.QIcon("assets/saveIcon.png"), "Save", self)
        saveAsAct = QtWidgets.QAction(
            QtGui.QIcon("assets/saveAsIcon.png"), "Save As", self
        )

        modeMenu = menubar.addMenu("Mode")
        snipAct = QtWidgets.QAction(QtGui.QIcon("assets/cameraIcon.png"), "Snip", self)
        snipAct.setShortcut(QtGui.QKeySequence("F1"))
        snipAct.triggered.connect(self.activateSnipping)
        videoAct = QtWidgets.QAction(QtGui.QIcon("assets/videoIcon.png"), "Video", self)
        videoAct.setShortcut("F2")
        soundAct = QtWidgets.QAction(QtGui.QIcon("assets/audioIcon.png"), "Sound", self)
        soundAct.setShortcut("F3")
        autoAct = QtWidgets.QAction(
            QtGui.QIcon("assets/automationIcon.png"), "Automation", self
        )
        autoAct.setShortcut("F4")

        helpMenu = menubar.addMenu("Help")
        helpAct = QtWidgets.QAction(QtGui.QIcon("assets/helpIcon.png"), "Help", self)
        aboutAct = QtWidgets.QAction(QtGui.QIcon("assets/aboutIcon.png"), "About", self)

        fileMenu.addAction(saveAct)
        fileMenu.addAction(saveAsAct)
        modeMenu.addAction(snipAct)
        modeMenu.addAction(videoAct)
        modeMenu.addAction(soundAct)
        modeMenu.addAction(autoAct)
        helpMenu.addAction(helpAct)
        helpMenu.addAction(aboutAct)

        self.snipper = SnippingWidget()
        self.snipper.closed.connect(self.on_closed)

    def activateSnipping(self):
        self.snipper.showFullScreen()
        self.hide()

    def on_closed(self):
        self.snipper.hide()
        self.show()


class SnippingWidget(QtWidgets.QMainWindow):
    closed = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(SnippingWidget, self).__init__(parent)
        self.setStyleSheet("background-color: transparent;")
        self.setWindowOpacity(0.2)

        self.outsideSquareColor = "red"
        self.squareThickness = 4

        self.start_point = QtCore.QPoint()
        self.end_point = QtCore.QPoint()

    def mousePressEvent(self, event):
        self.start_point = event.pos()
        self.end_point = event.pos()
        self.update()

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

    def mouseReleaseEvent(self, QMouseEvent):
        r = QtCore.QRect(self.start_point, self.end_point).normalized()
        img = ImageGrab.grab(bbox=r.getCoords())
        img.save("snips/testImage.png")
        self.closed.emit()

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setPen(
            QtGui.QPen(QtGui.QColor(self.outsideSquareColor), self.squareThickness)
        )
        trans = QtGui.QColor(255, 255, 255, 255)
        qp.setBrush(trans)

        outer = QtGui.QPainterPath()
        outer.addRect(QtCore.QRectF(self.rect()))

        inner = QtGui.QPainterPath()
        inner.addRect(QtCore.QRectF(self.start_point, self.end_point).normalized())
        r = outer - inner
        qp.drawPath(r)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    application = App()
    application.show()
    sys.exit(app.exec_())

更新:

class SnippingWidget(QtWidgets.QMainWindow):
    closed = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(SnippingWidget, self).__init__(parent)
        self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
        self.setStyleSheet("background:transparent;")
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)

        self.outsideSquareColor = "red"
        self.squareThickness = 4

        self.start_point = QtCore.QPoint()
        self.end_point = QtCore.QPoint()

    def mousePressEvent(self, event):
        self.start_point = event.pos()
        self.end_point = event.pos()
        self.update()

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

    def mouseReleaseEvent(self, QMouseEvent):
        r = QtCore.QRect(self.start_point, self.end_point).normalized()
        img = ImageGrab.grab(bbox=r.getCoords())
        img.save("snips/testImage.png")
        self.closed.emit()

    def paintEvent(self, event):
        trans = QtGui.QColor(255, 255, 255)
        r = QtCore.QRectF(self.start_point, self.end_point).normalized()

        qp = QtGui.QPainter(self)
        trans.setAlphaF(0.2)
        qp.setBrush(trans)
        outer = QtGui.QPainterPath()
        outer.addRect(QtCore.QRectF(self.rect()))
        inner = QtGui.QPainterPath()
        inner.addRect(r)
        r_path = outer - inner
        qp.drawPath(r_path)

        qp.setPen(
            QtGui.QPen(QtGui.QColor(self.outsideSquareColor), self.squareThickness)
        )
        trans.setAlphaF(0)
        qp.setBrush(trans)
        qp.drawRect(r)

这篇关于屏幕截图程序 - 透明截图区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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