I have an application where I have a transparent window, I am capturing the screen underneath and then displaying the same once user release the left mouse button. But the problem is I see only black screen, I tried saving the selected screenshot but still same black screen.
Here is my code :
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
import sys
class MainWindow(qtw.QMainWindow):
def __init__(self, *arg, **kwargs):
super().__init__()
self.setWindowFlag(qtc.Qt.FramelessWindowHint)
self.setAttribute(qtc.Qt.WA_TranslucentBackground)
borderWidget = qtw.QWidget(objectName='borderWidget')
self.setCentralWidget(borderWidget)
bgd = self.palette().color(qtg.QPalette.Window)
bgd.setAlphaF(.005)
self.setStyleSheet('''
#borderWidget {{
border: 3px solid blue;
background: {bgd};
}}
'''.format(bgd=bgd.name(bgd.HexArgb)))
self.setGeometry(100, 100, 400, 300)
self.showFullScreen()
self.setCursor(qtc.Qt.CrossCursor)
self.begin = None
self.end = None
self.show()
def paintEvent(self, event):
if self.begin:
qpbox = qtg.QPainter(self)
br = qtg.QBrush(qtg.QColor(100, 10, 10, 40))
qpbox.setBrush(br)
qpbox.drawRect(qtc.QRect(self.begin, self.end))
# close on right click
def mouseReleaseEvent(self, QMouseEvent):
if QMouseEvent.button() == qtc.Qt.RightButton:
self.close()
elif QMouseEvent.button() == qtc.Qt.LeftButton:
screen = qtw.QApplication.primaryScreen()
img = screen.grabWindow(self.winId(), self.begin.x(), self.end.y(), self.end.x() - self.begin.x() , self.end.y()-self.begin.y())
img.save('screenshot.png', 'png')
self.setStyleSheet("")
self.central_widget = qtw.QWidget()
label = qtw.QLabel(self)
label.setPixmap(img)
self.resize(img.width(), img.height())
self.setCentralWidget(label)
def mousePressEvent(self, QMouseEvent):
if QMouseEvent.button() == qtc.Qt.LeftButton:
self.begin = QMouseEvent.pos()
self.end = QMouseEvent.pos()
self.update()
def mouseMoveEvent(self, QMouseEvent):
self.end = QMouseEvent.pos()
self.update()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
w = MainWindow()
sys.exit(app.exec_())
You're grabbing from the current window, not from the desktop. While what you see is the desktop (due to the transparency), specifying a window id results in grabbing only that window without considering the background composition or any other foreign window.
If you want to grab from the screen, you need to use the root window's id, which is 0.
Also note that:
self.end
for the y
coordinate;class MainWindow(qtw.QMainWindow):
def __init__(self, *arg, **kwargs):
super().__init__()
self.setWindowFlags(self.windowFlags() | qtc.Qt.FramelessWindowHint)
self.setAttribute(qtc.Qt.WA_TranslucentBackground)
# use a QLabel
borderWidget = qtw.QLabel(objectName='borderWidget')
self.setCentralWidget(borderWidget)
self.setStyleSheet('''
#borderWidget {{
border: 3px solid blue;
background: transparent;
}}
''')
# pointless, you're showing the window in full screen
# self.setGeometry(100, 100, 400, 300)
# variables that are required for painting must be declared *before*
# calling any show* function; while this is generally not an issue,
# as painting will actually happen "later", it's conceptually wrong
# to declare a variable after it's (possibly) required by a function.
self.captureRect = None
self.showFullScreen()
self.setCursor(qtc.Qt.CrossCursor)
# unnecessary, you've already called showFullScreen
# self.show()
def paintEvent(self, event):
if self.captureRect:
qpbox = qtg.QPainter(self)
br = qtg.QBrush(qtg.QColor(100, 10, 10, 40))
qpbox.setBrush(br)
qpbox.drawRect(self.captureRect)
def mouseReleaseEvent(self, event):
if event.button() == qtc.Qt.RightButton:
self.close()
elif event.button() == qtc.Qt.LeftButton:
self.hide()
screen = qtw.QApplication.primaryScreen()
img = screen.grabWindow(0, *self.captureRect.getRect())
self.show()
img.save('screenshot.png', 'png')
self.setStyleSheet('')
self.centralWidget().setPixmap(img)
self.captureRect = None
def mousePressEvent(self, event):
if event.button() == qtc.Qt.LeftButton:
self.begin = event.pos()
self.captureRect = qtc.QRect(self.begin, qtc.QSize())
def mouseMoveEvent(self, event):
self.captureRect = qtc.QRect(self.begin, event.pos()).normalized()
self.update()
Note that I changed the event handler argument: QMouseEvent
is a class, and even though you're using the module (so the actual Qt class would be qtg.QMouseEvent
), that might be confusing and risky if you eventually decide to directly import classes; besides, only class and constant names should have capitalized names, not variables or functions.