关于Qt使用QPalette设置Qwidget背景色无效的解决办法及分析

因需要,需要重绘窗口的标题栏。

标题栏通过QWidget实现,可是当使用QPalette设置窗口的背景色后没有效果。

代码如下:

    //QWidget类构造函数内
    QPalette p;
    p.setBrush(this->backgroundRole(),QBrush(QColor(51,51,51)));
    this->setPalette(p);

如果这个QWidget直接show,是有背景色的,但是如果把它放到一个父Widget中时,它就没有了效果。
后来通过网上搜索,发现添加如下代码后就可以了:

    //QWidget类构造函数内
   this->setAutoFillBackground(true);

于是翻看帮助文档的autoFillBackground属性,我翻译如下:

  QWidget的autoFillBackground属性  bool类型

  这个属性决定widget的背景色是否自动填充。

  如果bool为真,这个属性会在widget触发PaintEvent之前引起Qt填充QWidget的背景色。

  填充的颜色是由widget的QPalette::window颜色角色所决定的。

  如果该widget没有设置WA_OpaquePaintEvent属性或者WA_NoSystemBackground属性,windows总是会使用QPalette::window颜色角色。

  注意:如果widget的父窗口有渐变的背景色填充,那么这个属性是不能被关闭的(也就是不能设置为false)。

  警告:混合使用此属性和Qt style sheet的时候需要注意,当一个widget拥有一个style sheet设置的背景色或者border-image,那么autoFillBackground属性自动关闭。

  该属性默认是关闭状态。

查看QPalette::window,它为一个窗口的标准的背景色。

然后查看QPalette的说明,发现有下面一句说明:

When you assign a new palette to a widget, the color roles from this palette are combined with the widget's default palette to form the 
widget
's final palette. The palette entry for the widget's background role is used to fill the widget's
background (see QWidget::autoFillBackground), and the foreground role initializes QPainter's pen.

我的翻译就是:

When you assign a new palette to a widget, the color roles from this palette are combined with the widget's default palette to 
form the widget
's final palette. The palette entry for the widget's background role is used to fill the widget's
background (see QWidget::autoFillBackground), and the foreground role initializes QPainter's pen. 当为widget设置一个新的palette的时候,那么设置的palette和widget的默认palette组合成最终的palette。这个palette调色板的背景角色用于填充widget 的背景色(autoFillBackground),同样,前景角色用来初始化笔的颜色,也就是前景色。

既然setPalette是能够设置窗口的背景色,而且当widget没有父窗口是能够成功设置背景色的。
于是我感觉问题可能是出在这句话:

如果该widget没有设置WA_OpaquePaintEvent属性或者WA_NoSystemBackground属性,windows总是会使用QPalette::window颜色角色。

于是在构造函数和paintEvent中都qDebug输出this->Palette().background();
发现结果是一样的,这就证明问题不是出在这个位置。

仔细观看setPalette的说明发现:

QWidget propagates explicit palette roles from parent to child. 
If you assign a brush or color to a specific role on a palette and 
assign that palette to a widget, that role will propagate to all the 
widget's children, overriding any system defaults for that role. 
也就是说widget会清晰的传递自己的palette到孩子类。

于是我把父窗口的背景色设置为红色,发现widget的背景色也是红色了(通过qDebug输出widget的background根本不是红色)。
这也就是说明,如果没有设置autoFillBackground,那么子窗口的setPalette是不生效的。也就是会是使用从父类传递来的"默认"背景色。

我说大牛门把setAutoFillBackground函数的释义为不从父窗口继承背景色,当初我还有点怀疑,现在算是理解了,虽然不知道对不对。  新手,学习ing...

原文地址:https://www.cnblogs.com/justwake/p/justwake_widget_autoFillBackground.html