如何使背景颜色与表单背景颜色相同?

How to make the background color the same as the form background?

在 PyQt5 中,我从 QTabWidget 得到了一些意外的行为,背景似乎是白色而不是默认的表单颜色(大致为浅灰色)。这是一个例子:

# QTabWidget2.py

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QHBoxLayout, QVBoxLayout, QTabWidget, \
    QGraphicsView, QFrame, QGridLayout
from PyQt5.QtGui import QPalette
from PyQt5.Qt import Qt


def main():
    app = QApplication([])
    mainForm = MainForm()
    mainForm.show()
    app.exec()
# end main

class MainForm(QWidget):

    def __init__(self):
        super().__init__()

        # set default form size and location
        self.setGeometry(300, 300, 800, 600)

        # declare a graphics view
        self.bigLabel = QLabel('Big Label')
        self.setFontSize(self.bigLabel, 18)
        self.bigLabel.setAlignment(Qt.AlignCenter)
        self.bigLabel.setFrameStyle(QFrame.Panel)

        # declare a small label and a button
        self.label = QLabel('Label')
        self.setFontSize(self.label, 12)
        self.label.setAlignment(Qt.AlignCenter)
        self.button = QPushButton('Button')
        self.setFontSize(self.button, 12)

        self.vboxLayout = QVBoxLayout()
        self.vboxLayout.addWidget(self.label)
        self.vboxLayout.addWidget(self.button)
        self.vboxLayout.addStretch(1)

        self.hboxLayout = QHBoxLayout()
        self.hboxLayout.addWidget(self.bigLabel, 10)
        self.hboxLayout.addLayout(self.vboxLayout, 1)

        self.containerWidget = QWidget()
        self.containerWidget.setLayout(self.hboxLayout)

        self.tabWidget = QTabWidget()
        self.tabWidget.addTab(self.containerWidget, 'My Tab')

        self.gridLayout = QGridLayout()

        self.gridLayout.addWidget(self.tabWidget)

        self.setLayout(self.gridLayout)

    # end function

    def setFontSize(self, widget, fontSize):
        font = widget.font()
        font.setPointSize(fontSize)
        widget.setFont(font)
    # end function

# end class

if __name__ == '__main__':
    main()

这是 Ubuntu 18.04 上的样子:

我的问题是,如何使 QTabWidget 背景与表单(在本例中为 QWidget)背景颜色相同?

我尝试过的一些事情:

很多小部件都有这样的功能:

someWidget.setBackgroundBrush(self.palette().brush(QPalette.Window))

但是 QTabWidget 似乎没有 setBackgroundBrush 或我能找到的等效项。

我发现一些帖子建议使用样式表来实现这一点,但我不确定如何设置它。我需要 sub-class QTabWidget 来实现吗?另外,我怎样才能获得默认的背景颜色?我可以使用简单的猜测和检查来接近,但它可能会在不同的平台上略有变化,所以这不是特别可取的。

--- 编辑 ---

啊啊啊啊啊啊!!! Qt 有时真的很令人沮丧。如果我在声明 QTabWidget:

之后添加它
        widgetColor = self.palette().color(QPalette.Background)
        widgetColorRgba = widgetColor.red(), widgetColor.green(), widgetColor.blue(), widgetColor.alpha()
        print('widgetColorRgb = ' + str(widgetColorRgba))

        styleSheetString = 'background-color: rgba(' + str(widgetColorRgba[0]) + ', ' + \
            str(widgetColorRgba[1]) + ', ' + str(widgetColorRgba[2]) + ', ' + str(widgetColorRgba[3]) + ');'

        print('styleSheetString = ' + str(styleSheetString))

        # this line works
        self.tabWidget.setStyleSheet(styleSheetString)

        # this line does not work !!!
        self.tabWidget.tabBar().setStyleSheet(styleSheetString)

它正确地将 QTabWidget 的主体更改为默认的表单背景颜色,但它不会更改选项卡的颜色!!

这个问题有两种可能的解决方案。

此行为的主要原因可以在正在使用的样式中找到。

每种 Qt 样式决定如何使用调色板颜色来绘制小部件。这意味着即使您为(比方说)背景设置了特定的颜色,也不能保证小部件将具有该特定的背景颜色。

如果你想想按钮,这个概念会更好地解释:它们通常有一个 "shade" 渐变,这是基于 Button 颜色角色,但背景不是 正好那个颜色。在下图中,我展示了一个按钮,我为其按钮角色设置了纯红色 (#ff0000),但是,如您所见,它是 而非 红色:

调色板颜色实际上是一个参考。

有些widgets的绘制行为没有特定的角色,使用哪个角色以及如何使用由样式决定,QTabWidget就是这种情况。 在 Linux 上,默认样式通常是 "Fusion",它使用 Button 角色来绘制选项卡小部件的背景,但是当绘制该背景时,渐变 based在那个 color 上使用。同样,为 Button 角色(又名选项卡小部件背景)应用了全红色,这不是真正的红色:

对此有两种可能的解决方案。

1。使用另一种风格

在处理QTabWidget时,"Oxygen"样式似乎与父背景更加连贯。

def main():
    app = QApplication([])
    app.setStyle(QStyleFactory.create('oxygen'))

要知道系统上安装了哪些样式,只需调用QStyleFactory.keys()。请注意,并非所有样式都适用于每个系统。通常,"Fusion" 和 "Windows" 可用,这意味着如果您尝试访问 "Oxygen" 样式但未安装,则将使用回退样式。

2。也为选项卡栏使用全面的样式表

您的选项卡未使用样式表设置的背景的原因是样式(融合)仍在使用上述应用于背景颜色的渐变,这是因为选项卡可以有不同的选中与否的颜色(具体来说,如果选中则比背景浅,否则比背景深)。
为避免这种情况,您需要为所有标签栏伪状态设置样式表。

    bgd = 'rgba({}, {}, {}, {})'.format(*self.palette().color(QPalette.Window).getRgb())

    # get the default margins for layouts and use them for text padding of
    # the tab; obviously, you can use your own default padding instead
    margins = []
    for side in (QStyle.PM_LayoutTopMargin, QStyle.PM_LayoutRightMargin, QStyle.PM_LayoutBottomMargin, QStyle.PM_LayoutLeftMargin):
        margin = self.style().pixelMetric(side, None, None)
        if side in (QStyle.PM_LayoutTopMargin, QStyle.PM_LayoutBottomMargin):
            margin //= 2
        margins.append('{}px'.format(margin))
    padding = ' '.join(margins)

    self.tabWidget.setStyleSheet('''
        /* this selector applies the background color only to QWidgets that
        are direct children of QTabWidget */
        QTabWidget > QWidget {{
            background-color: {bgd};
        }}
        QTabBar::tab {{
            padding: {padding};
            border-left: 1px solid palette(mid);
            border-right: 1px solid palette(mid);
            border-top: 1px solid palette(mid);
            border-top-left-radius: 2px;
            border-top-right-radius: 2px;
            border-bottom: 1px solid palette(mid);
            margin: 0;
        }}
        QTabBar::tab:selected {{
            border-color: palette(dark);
            border-bottom: none;
        }}
        QTabBar::tab:!selected {{
            margin-top: 2px;
            margin-bottom: -2px;
        }}
    '''.format(bgd=bgd, padding=padding))

这就是结果:

我喜欢@musicamente 的回答。但值得指出的是,QTabWidget的背景颜色可以在QTabWidget的样式表属性中控制。

根据docs,一个QTabWidget主要由一个QTabBar和一个QStackedWidget组成。您在样式表中使用 QTabBar 键来控制选项卡颜色,并使用 QStackedWidget 键来控制每个单独的页面。 Qt默认的浅灰色windows是#f0f0f0,所以可以用这个作为颜色。这是一个可以输入 Designer/Creator 的字符串(或者您可以使用 setStyleSheet('string') 以编程方式输入):

QTabBar::tab {
    padding: 8px;
    background-color: #f0f0f0;
    border: 1px solid palette(mid);
    border-radius: 2px;
    margin: 0;
}
QTabBar::tab:selected {
    border-bottom: none;}
QTabBar::tab:!selected {
    margin-top: 2px;
    margin-bottom: -2px;
    border-bottom: none;}
QStackedWidget {
    background-color: #f0f0f0;
}

这给出了

但是,我更喜欢选择的选项卡是不同的颜色,所以我只接受 QTabBar 的默认值。

QStackedWidget {
    background-color: #f0f0f0;
}

这给出了