【问题标题】:Screen Snipping Program - Transparent Snipping Area屏幕截图程序 - 透明截图区域
【发布时间】:2020-09-12 18:37:54
【问题描述】:

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

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_())

【问题讨论】:

    标签: python python-3.x user-interface pyqt5


    【解决方案1】:

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

    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)
    

    【讨论】:

    • 您好 eyllanesc,感谢您愿意帮助我解决此问题。我最初在黑色背景下尝试了您的解决方案,它似乎有效。不幸的是,里面的正方形不是完全透明的。正方形在白色背景下仍有一定程度的不透明性。
    • 不幸的是,现在外面是灰色的,里面是黑色的。外部和内部现在都是 100% 不透明的。
    • @BrettLapierre 你的操作系统是什么?并尝试删除self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True)。我已经在 Linux 上测试过了。 PyQt5 5.14.2 y Python 3.8.2,它可以正常工作。
    • 我在 Windows 10 上,删除该行时它仍然无法正常工作。内部和外部仍然是不透明的。
    • @BrettLapierre 尝试添加self.setStyleSheet("background:transparent;")self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
    猜你喜欢
    • 2015-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-31
    相关资源
    最近更新 更多