Reputation: 533
So I recently found out about the concept of "see through hole" on windows.
Managed to do it in PyQT5 using following code:
import sys
from PyQt5.QtCore import Qt, QRect, QPoint
from PyQt5.QtGui import QPainter, QBrush, QColor, QRegion
from PyQt5.QtWidgets import QApplication, QWidget
class SeeThroughHoleWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.dragging = False
self.drag_start_position = QPoint()
def initUI(self):
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setGeometry(100, 100, 800, 600)
self.setWindowTitle('See-Through Hole Window')
self.hole_rect = QRect(300, 200, 200, 200)
self.updateMask()
def updateMask(self):
region = QRegion(self.rect())
region -= QRegion(self.hole_rect)
self.setMask(region)
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setBrush(QBrush(QColor(255, 255, 255, 255)))
painter.setPen(Qt.NoPen)
painter.drawRect(self.rect())
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.dragging = True
self.drag_start_position = event.globalPos() - self.frameGeometry().topLeft()
event.accept()
def mouseMoveEvent(self, event):
if self.dragging:
self.move(event.globalPos() - self.drag_start_position)
event.accept()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.dragging = False
event.accept()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SeeThroughHoleWindow()
ex.show()
sys.exit(app.exec_())
But then I noticed it's not as obvious to me if it's possible to draw on top of the see-through hole? I know it's possible in Tkinter for example, but I did not find any way to do that with PyQT5.
My Goal would be for example to draw bounding boxes on top, but not with the mouse (since the mouse events pass through the see-through hole) for computer vision related projects.
Here is an example of what I tried to do using EasyOCR and mss:
import sys
import cv2
import numpy as np
import mss
import easyocr
from PyQt5.QtCore import Qt, QRect, QPoint, QTimer
from PyQt5.QtGui import QPainter, QBrush, QColor, QRegion, QPen
from PyQt5.QtWidgets import QApplication, QWidget
class SeeThroughHoleWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.dragging = False
self.drag_start_position = QPoint()
self.reader = easyocr.Reader(['en'])
self.bounding_boxes = []
# Set up a timer to periodically capture and process the screen
self.timer = QTimer(self)
self.timer.timeout.connect(self.capture_and_process)
self.timer.start(1000) # Adjust the interval as needed
def initUI(self):
self.setWindowFlags(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setGeometry(100, 100, 800, 600)
self.setWindowTitle('See-Through Hole Window')
self.hole_rect = QRect(300, 200, 200, 200)
self.updateMask()
def updateMask(self):
region = QRegion(self.rect())
region -= QRegion(self.hole_rect)
self.setMask(region)
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setBrush(QBrush(QColor(255, 255, 255, 255)))
painter.setPen(Qt.NoPen)
painter.drawRect(self.rect())
# Draw bounding boxes over the see-through hole
painter.setPen(QPen(Qt.red, 2))
for box in self.bounding_boxes:
x1, y1, x2, y2 = box
rect = QRect(x1 + self.hole_rect.left(), y1 + self.hole_rect.top(),
x2 - x1, y2 - y1)
painter.drawRect(rect)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.dragging = True
self.drag_start_position = event.globalPos() - self.frameGeometry().topLeft()
event.accept()
def mouseMoveEvent(self, event):
if self.dragging:
self.move(event.globalPos() - self.drag_start_position)
event.accept()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.dragging = False
event.accept()
def capture_and_process(self):
with mss.mss() as sct:
monitor = {
"top": self.y() + self.hole_rect.top(),
"left": self.x() + self.hole_rect.left(),
"width": self.hole_rect.width(),
"height": self.hole_rect.height()
}
img = sct.grab(monitor)
img_rgb = np.array(img)
# Convert the image from BGRA to RGB
img_rgb = cv2.cvtColor(img_rgb, cv2.COLOR_BGRA2RGB)
# Read text from the image
self.bounding_boxes = []
results = self.reader.readtext(img_rgb, detail=1)
for (bbox, text, prob) in results:
(top_left, top_right, bottom_right, bottom_left) = bbox
x1, y1 = int(top_left[0]), int(top_left[1])
x2, y2 = int(bottom_right[0]), int(bottom_right[1])
self.bounding_boxes.append((x1, y1, x2, y2))
self.update()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SeeThroughHoleWindow()
ex.show()
sys.exit(app.exec_())
But only part of the edges of some bounding boxes are shown on the white part of the window.
Upvotes: 0
Views: 46