PyQt5:样式表和从 QWidget 继承

问题描述

我的代码生成一个包含两个 QWidget 的窗口,一个是红色 (wg1),一个是蓝色 (wg2)。如果它们变成继承自 QWidget 的 Fields(注释掉),它们的颜色就会消失。

我的问题是:为什么 Field(继承自 QWidget)有必要使用该行

self.setAttribute(Qt.WA_StyledBackground,True)

在它的 __init__ 方法中,而 QWidget 不需要这一行?

import sys
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QWidget,QApplication,qgridLayout
from PyQt5.QtCore import Qt

class Field(QWidget):
    def __init__(self,name):
        super().__init__()
        self.name = name
        # self.setAttribute(Qt.WA_StyledBackground,True)# !!!
        
    def mousepressEvent(self,event):
        print(f" click makes {self.name} green")
        self.setStyleSheet("background: #00ff00;")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    root = QWidget()
    grid = qgridLayout()
    root.setLayout(grid)
    root.resize(300,100)

    wg1 = QWidget()
    wg2 = QWidget()
    # wg1 = Field('wg1')
    # wg2 = Field('wg2')

    wg1.setStyleSheet("background: #aa1111;")
    grid.addWidget(wg1,0)

    wg2.setStyleSheet("background: #1111aa;")
    grid.addWidget(wg2,2)

    root.show()
    sys.exit(app.exec_())

解决方法

解释位于样式表参考的 section related to QWidget 中:

如果您从 QWidget 继承子类,您需要为您的自定义 QWidget 提供一个paintEvent,如下所示:

默认情况下,QWidget 会这样做,但 QWidget 子类不会,因此您要么设置标志,要么实现paintEvent。

无论如何,请考虑使用 stylesheet selectors 并避免使用通用/通用语法,因为它们通常会导致复杂的子小部件出现意外行为。