I have a Python application that captures a region of the screen using PySide6 and PIL libraries.
The application works well on 1980×1080 resolution monitor. However, when using it on my primary monitor with a resolution 2560×1600 and a scaling factor of 175%, there is a significant mismatch between the captured region and the actual screenshot.
I suspect this discrepancy is due to the monitor scaling factor affecting coordinates calculations. How can I adjust the coordinates to account for the monitor scaling factor?
Additionally, I would like to extend the screen capture functionally to work on dual monitors, capturing regions from both monitors simultaneously. What approach should I take to implement this feature?
# source from https://github.com/harupy/snipping-tool
import sys
from PySide6 import QtCore, QtGui, QtWidgets
import tkinter as tk
from PIL import ImageGrab
import numpy as np
import cv2
import pygetwindow as gw
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
root = tk.Tk()
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.withdraw() # Hide the root window
screen_geometry = gw.getWindowsWithTitle(gw.getActiveWindow().title)[0]
virtual_screen_width = screen_geometry.width
virtual_screen_height = screen_geometry.height
self.setGeometry(0, 0, virtual_screen_width, virtual_screen_height)
self.setWindowTitle(' ')
self.begin = QtCore.QPoint()
self.end = QtCore.QPoint()
self.setWindowOpacity(0.3)
self.num_snip = 0
self.is_snipping = False
QtWidgets.QApplication.setOverrideCursor(
QtGui.QCursor(QtCore.Qt.CrossCursor)
)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
print('Capture the screen...')
print('Press q if you want to quit...')
self.show()
def paintEvent(self, event):
if self.is_snipping:
brush_color = (0, 0, 0, 0)
lw = 0
opacity = 0
else:
brush_color = (128, 128, 255, 128)
lw = 3
opacity = 0.3
self.setWindowOpacity(opacity)
qp = QtGui.QPainter(self)
qp.setPen(QtGui.QPen(QtGui.QColor('black'), lw))
qp.setBrush(QtGui.QColor(*brush_color))
qp.drawRect(QtCore.QRectF(self.begin, self.end))
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Q:
print('Quit')
self.close()
event.accept()
def mousePressEvent(self, event):
self.begin = event.position()
self.end = self.begin
self.update()
def mouseMoveEvent(self, event):
self.end = event.position()
self.update()
def mouseReleaseEvent(self, event):
self.num_snip += 1
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())
self.is_snipping = True
self.repaint()
QtWidgets.QApplication.processEvents()
img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
self.is_snipping = False
self.repaint()
QtWidgets.QApplication.processEvents()
img_name = 'snip{}.png'.format(self.num_snip)
img.save(img_name)
print(img_name, 'saved')
img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWidget()
window.show()
app.aboutToQuit.connect(app.deleteLater)
sys.exit(app.exec())
I am currently exploring the screeninfo
library to address issues related to screen resolution and DPI scaling..
Sungbin Lee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.