Я пытаюсь создать настольное приложение для Windows 10 с помощью PyQt.
Приложение будет оверлеем, поэтому оно должно быть прозрачным, кликабельным и всегда сверху. Детектор объектов обнаружит некоторые интересующие области, и в этой области будет нарисован прямоугольник.
Накладка почти в порядке. Прямо сейчас он может рисовать случайные прямоугольники, и, пока фон прозрачен, вы можете щелкать фон. Проблема в том, что я не могу нажимать на прямоугольники.
Я попробовал атрибут WA_TransparentForMouseEvents
, но он не работал правильно. Когда я устанавливаю этот атрибут, кнопки перестают работать (я ожидал такого поведения, и мне все равно, поскольку кнопки предназначены только для отладки), но я все еще не могу нажимать кнопки или прямоугольники.
Это мой пример кода:
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QBrush, QColor, QPainter, QPen
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QStackedWidget
import numpy as np
class OverlayScreen(QMainWindow):
def __init__(self):
super().__init__()
self.setFixedHeight(1080)
self.setFixedWidth(1920)
self.setObjectName("overlay")
self.setStyleSheet("QMainWindow#overlay {background-color: rgba(0, 0, 0, 125)}")
self.bg_transparent = False
self.toggle_btn = QPushButton("Toggle", self)
self.toggle_btn.setGeometry(200, 150, 100, 30)
self.toggle_btn.clicked.connect(self.toggle_background)
self.draw_btn = QPushButton("Draw rectangle", self)
self.draw_btn.setGeometry(320, 150, 100, 30)
self.draw_btn.clicked.connect(self.draw_rectangle)
self.rectangles = []
self.close_btn = QPushButton("Close", self)
self.close_btn.setGeometry(200, 200, 100, 30)
self.close_btn.clicked.connect(sys.exit)
def toggle_background(self):
self.bg_transparent = not self.bg_transparent
if self.bg_transparent:
self.setStyleSheet("QMainWindow#overlay {background-color: transparent}")
else:
self.setStyleSheet("QMainWindow#overlay {background-color: rgba(0, 0, 0, 125)}")
def draw_rectangle(self):
# self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents)
rect = [np.random.randint(1920 - 150),
np.random.randint(1080 - 100),
np.random.randint(150),
np.random.randint(100)]
self.rectangles.append(rect)
self.update()
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.GlobalColor.green, 1))
painter.setBrush(QBrush(QColor(0, 255, 0, 80), Qt.BrushStyle.SolidPattern))
for rect in self.rectangles:
painter.drawRect(*rect)
painter.end()
if __name__ == "__main__":
app = QApplication(sys.argv)
main = QStackedWidget()
main.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
main.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint)
main.move(0, 0)
overlay = OverlayScreen()
main.addWidget(overlay)
main.show()
try:
sys.exit(app.exec())
except Exception:
print("Error")
WA_TransparentForMouseEvents
в событии рисования бесполезна, так как эти вещи совершенно не связаны между собой: пытаться установить этот атрибут в событиях рисования — плохая идея (такие события могут происходить очень часто), а установка атрибута действует на все виджет в любом случае. Возможно, вам следует подумать о маскировании, см. этот частично связанный ответ: Можно ли создать QMainWindow только с внешней границей? а>. - person musicamante   schedule 04.06.2021