I am making an imitation of the built-in Win+Shift+S screenshot function on windows. I am not very familiar with QPainter. Just like the windows function, I want to darken the background, but highlight the actual selected rect the user does. Everything works, but since the background is dark the actual image is darkened. Is there a workaround for this?
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt, QPoint, QRect, Qt
from PyQt5.QtGui import QPixmap, QPen, QPainter, QColor, QBrush
from win32api import GetSystemMetrics, GetKeyState, GetCursorPos
import pyautogui
import PIL
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.setFixedSize(GetSystemMetrics(0), GetSystemMetrics(1))
self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground, True)
self.setWindowOpacity(.9)
self.setWindowFlag(Qt.Tool)
self.pix = QPixmap(self.rect().size())
(self.begin, self.destination) = (QPoint(), QPoint())
def paintEvent(self, event):
painter = QPainter(self)
painter.setOpacity(0.2)
painter.setBrush(Qt.black) #ACTUAL BACKGROUDN
painter.setPen(QPen(Qt.white)) #BORDER OF THE RECTANGLE
painter.drawRect(self.rect())
painter.drawPixmap(QPoint(), self.pix)
if not self.begin.isNull() and not self.destination.isNull():
rect = QRect(self.begin, self.destination)
painter.drawRect(rect.normalized())
def mousePressEvent(self, event):
global initial_x, initial_y
initial_x, initial_y = GetCursorPos()
print('down')
if event.buttons() & Qt.LeftButton:
self.begin = event.pos()
self.destination = self.begin
self.update()
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
self.destination = event.pos()
self.update()
def mouseReleaseEvent(self, event):
final_x, final_y = GetCursorPos()
print('up')
a = pyautogui.screenshot(region=(initial_x,initial_y, (final_x - initial_x), (final_y - initial_y)))
a.save(r'C:\Users\ohtitus\Documents\New folder\main.png')
if event.button() & Qt.LeftButton:
rect = QRect(self.begin, self.destination)
painter = QPainter(self.pix)
painter.drawRect(rect.normalized())
painter.fillRect(rect, QColor(0,0,0,0))
(self.begin, self.destination) = (QPoint(), QPoint())
self.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setOverrideCursor(Qt.CrossCursor)
app.setStyleSheet("background-color: rgb(0, 0, 0)")
app.setStyleSheet('''
QWidget {
font-size: 30px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec_())
except SystemExit:
pass
In your paintEvent(self, event)
method, add two lines of code before drawing the transparent rectangle which specifies the region to be captured
if not self.begin.isNull() and not self.destination.isNull():
painter.setOpacity(0.0) # Added
painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Source) # Added
rect = QRect(self.begin, self.destination)
painter.drawRect(rect.normalized()) # Origianl code
So paintEvent(self, event)
will look like this
def paintEvent(self, event):
painter = QPainter(self)
painter.setOpacity(0.2)
painter.setBrush(Qt.black) # ACTUAL BACKGROUDN
painter.setPen(QPen(Qt.white)) # BORDER OF THE RECTANGLE
painter.drawRect(self.rect())
painter.drawPixmap(QPoint(), self.pix)
if not self.begin.isNull() and not self.destination.isNull():
painter.setOpacity(0.0)
painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Source)
rect = QRect(self.begin, self.destination)
painter.drawRect(rect.normalized())
Code explanation
painter.setOpacity(0.0)
needs to draw a transparent figure
painter.setCompositionMode( mode )
changes the way how a new figure (source) will be merged into the the original drawing (destination).
By default, it is set to CompositionMode.CompositionMode_SourceOver
, the mode where a source will overwrite a destination while the destiantion still appear in a transparent region of the source.
In your case, you want to make some part of the destination transparent . You can achieve this by making transparent source to overwrite the destination. The mode CompositionMode.CompositionMode_Source
does it.
Refer to https://doc.qt.io/archives/qt-4.8/qpainter.html#CompositionMode-enum for more information about the composition mode.