在 PyQt 中设置 `WA_TransparentForMouseEvents` 属性后,如何使 Qt window 再次收到点击?

How do I make Qt window receive clicks again after setting `WA_TransparentForMouseEvents` attribute in PyQt?

根据文档,为了取消设置属性,我需要将 False 作为第二个参数传递给小部件的 setAttribute 方法。我已经这样做了,但出于某种原因 window 对鼠标事件保持透明。

这是一个最小的可重现示例:

import sys

from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from PyQt6.QtCore import Qt


class Main(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(400, 400)
        self.setWindowTitle('Main')

        self.state = False

        self.button = QPushButton(f'Secondary window can be clicked through: {self.state}')
        self.button.clicked.connect(self.button_click)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.button)
        self.setLayout(self.layout)

        self.secondary = Secondary()

    def button_click(self):
        self.state = not self.state
        self.button.setText(f'Secondary window can be clicked through: {self.state}')
        self.secondary.set_click_through_state(self.state)


class Secondary(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(400, 400)
        self.setWindowOpacity(0.8)
        self.setWindowTitle('Secondary')

    def set_click_through_state(self, state: bool):
        print('Received new state:', state)
        self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, on=state)

        self.hide()
        if state:
            self.setWindowFlags(
                self.windowFlags()
                | Qt.WindowType.FramelessWindowHint
                | Qt.WindowType.WindowStaysOnTopHint
            )
        else:
            self.setWindowFlags(
                self.windowFlags()
                & ~Qt.WindowType.FramelessWindowHint
                & ~Qt.WindowType.WindowStaysOnTopHint
            )
        self.show()

        print('Attribute is set:', self.testAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents))


if __name__ == '__main__':
    app = QApplication(sys.argv)

    main = Main()
    main.show()
    main.secondary.show()

    sys.exit(app.exec())

在 Windows 10 / Python 3.10 / PyQt6 上测试。

事实证明,为小部件设置 WA_TransparentForMouseEvents 属性也会向其添加 WindowTransparentForInput 标志。我不确定为什么,但是 取消设置属性时不会删除此标志

只需从 window 中删除 WindowTransparentForInput 标志即可解决问题:

widget.setWindowFlags(
    widget.windowFlags() & ~Qt.WindowType.WindowTransparentForInput
)