为自定义QWidget设置背景颜色

6
我正在尝试创建一个自定义的QWidget(来自PyQt5),可以更改其背景颜色。 然而,所有设置背景颜色的标准方法似乎都不能用于自定义QWidget类。
到目前为止,我已经尝试通过QSS样式表和设置调色板来更改颜色。这对常规QWidget有效,但是出于某种原因不适用于自定义小部件。
在C ++文档中,我找到了自定义QWidgets需要paintEvent()函数的参考https://wiki.qt.io/How_to_Change_the_Background_Color_of_QWidget 并且在Python中也找到了一个引用。 但是,实施链接的paintevent失败,因为在PyQt5中似乎不存在QStyleOption。
下面显示了我创建的QWidget类的高级别和我用于Widget的QSS(样式已在父Widget中设置,但尝试直接设置它)。
class AlarmWidget(QWidget):
    def __init__(self, alarm, parent=None):
        super(AlarmWidget, self).__init__(parent)
        self.setFixedHeight(200)
        self.setProperty("active", True)

        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), PyQt5.QtCore.Qt.red)
        self.setPalette(p)

AlarmWidget {
  background-color: red
}

总体来说,无论我做什么,它都不允许我为自定义QWidget设置背景颜色,非常需要帮助。

2个回答

8

最简单的修复方法是这样的:

class AlarmWidget(QWidget):
    def __init__(self, alarm, parent=None):
    ...
    self.setAttribute(QtCore.Qt.WA_StyledBackground, True)
    self.setStyleSheet('background-color: red')

每当样式表应用于自定义小部件或其祖先小部件之一时,就会出现此问题。引用自QWidget.setPalette文档:

警告:不要将此函数与Qt样式表一起使用。 使用样式表时,可以使用“颜色”、“背景颜色”、“选择颜色”、“选择背景颜色”和“交替背景颜色”来自定义小部件的调色板。

然而,这个失败了提到的是,出于性能原因,默认情况下禁用自定义小部件的样式表支持。因此,为了使您的示例正常工作,必须(1)通过样式表设置背景颜色,并且(2)显式启用WA_StyledBackground小部件属性的样式表支持。
下面是一个演示此功能的最小示例:
import sys
from PyQt5 import QtCore, QtWidgets

class AlarmWidget(QtWidgets.QWidget):
    def __init__(self, alarm, parent=None):
        super(AlarmWidget, self).__init__(parent)
        self.setFixedHeight(200)
#         self.setAutoFillBackground(True)
#         p = self.palette()
#         p.setColor(self.backgroundRole(), QtCore.Qt.red)
#         self.setPalette(p)
        self.setAttribute(QtCore.Qt.WA_StyledBackground, True)
        self.setStyleSheet('background-color: red')

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.setStyleSheet('background-color: green')
        self.widget = AlarmWidget('')
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.widget)

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setWindowTitle('BG Colour Test')
    window.setGeometry(600, 100, 300, 200)
    window.show()
    sys.exit(app.exec_())

这应该显示一个带有绿色边框的红色矩形窗口,如下图所示:

screenshot

为了进一步测试,仅在AlarmWidget类中设置调色板,但不在Window类中设置样式表。这应该显示一个没有绿色边框的红色矩形。最后,在两个类中仅设置样式表 - 但不包括setAttribute行。这应该显示一个纯绿色的矩形,没有内部红色矩形(即自定义小部件上的样式表不再应用)。

3

所有方法对我都有效,但如果您想实现paintEvent,则PyQt5的翻译如下:

class AlarmWidget(QtWidgets.QWidget):
    # ...

    def paintEvent(self, event):
        opt = QtWidgets.QStyleOption()
        opt.initFrom(self)
        p = QtGui.QPainter(self)
        self.style().drawPrimitive(QtWidgets.QStyle.PE_Widget, opt, p, self)

谢谢你的回答。如果可以的话,我也会将其标记为正确的解决方案,但我认为另一个答案更全面。你是从哪里找到如何做这个的?我花了很长时间搜索如何编写这种paintevent。 - rmasp98
@rmasp98 只有从Qt4到Qt5所做的修改:1)将init()更改为initFrom(),2)将一些类从QtGui移动到QtWidgets。 - eyllanesc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接