假设现在有两个重叠显示的 QWidget 部件,widget_1 与 widget_2。二者无父子关系,只是位置重叠,widget_1 在 widget_2 之上,如下图所示。
这个时候如果鼠标点击在 widget_1 上,widget_2 是不会响应鼠标事件的。因为事件被位于上层的 widget_1 捕获了。
如果我们想让鼠标事件穿透 widget_1,由 widget_2 捕获。就可以给 widget_1 设置 WA_TransparentForMouseEvents 属性,让它对所有鼠标事件“透明”。
widget_1.setAttribute(QtCore.Qt.WidgetAttribute.WA_TransparentForMouseEvents)
QLabel 显示富文本时会吞掉鼠标事件
今天还遇到一个问题,当 QLabel 作为子控件的时候,如果是 PlainText 模式,那么在 QLabel 上触发的鼠标事件会自动传递给父控件。但如果 QLabel 处于 RichText 模式,那么它会响应并且吞掉鼠标事件!事件无法传递给父控件!
BUG 复现代码如下:
class Window(QMainWindow): def __init__(self): super().__init__() self.label = MyLabel(self) self.label.resize(200, 50) self.label.setStyleSheet("border: 1px solid black;") text = "Test mouse events on here" self.label.setText(text) self.label.setText("<p style='color:red;'>{}</p>".format(text)) # self.label.setAttribute(QtCore.Qt.WidgetAttribute.WA_TransparentForMouseEvents) def mouseReleaseEvent(self, e): if e.button() == QtCore.Qt.LeftButton: print("Left") if e.button() == QtCore.Qt.RightButton: print("Right") pass App = QApplication(sys.argv) window = Window() window.show() sys.exit(App.exec())
有两种解决办法:
(1)给 label 设置 setAttribute(QtCore.Qt.WidgetAttribute.WA_TransparentForMouseEvents)
,这样 label 自己就不响应鼠标事件,也不会吞掉事件而是直接传递给父节点。
(2)派生 QLabel,重写 mouseReleaseEvent() 方法,在该方法中,判断如果可能是富文本,就手动将鼠标事件传递给父节点。
def mouseReleaseEvent(self, event): if QtGui.Qt.mightBeRichText(self.text()): self.parent().mouseReleaseEvent(event) super().mouseReleaseEvent(event) pass