如何使背景颜色与表单背景相同? [英] How to make the background color the same as the form background?

查看:80
本文介绍了如何使背景颜色与表单背景相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In PyQt5 I'm getting some unexpected behavior from QTabWidget, the background seems to be white instead of the default form color (roughly light gray). Here is an example:

# 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 上的样子:

Here is what it looks like on Ubuntu 18.04:

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

My question is, how can I make the QTabWidget background the same color as the form (in this case a QWidget) background?

我尝试过的一些事情:

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

Many widgets have a function like this:

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

但 QTabWidget 似乎没有 setBackgroundBrush 或我能找到的等价物.

But QTabWidget does not seem to have setBackgroundBrush or an equivalent I can find.

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

I've found some posts that suggest to use style sheets to achieve this, but I'm not sure how to set this up. Would I need to sub-class QTabWidget to achieve this? Also, how could I get the default background form color? I could use simple guess and check to get close, but then it may change slightly across different platforms so this is not especially desirable.

--- 编辑---

Arrrrrrrggggggg !!!Qt 有时真的很令人沮丧.如果我在声明 QTabWidget 之后添加这个:

Arrrrrrrggggggg !!! Qt can be really frustrating sometimes. If I add this just after declaring the 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 的主体更改为默认的表单背景颜色,但它并没有更改选项卡的颜色!!

It correctly changes the body of the QTabWidget to the default form background color, but it does not change the color of the tab!!

推荐答案

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

There are two possible solutions for this problem.

这种行为的主要原因可以在所使用的样式中找到.

The main reason for this behavior can be found in the style that is being used.

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

Each Qt style decides how the palette colors are used to paint a widget. This means that even if you set a specific color for (let's say) the background, it is not guaranteed that the widget will have that specific background color.

如果您考虑一下按钮,可以更好地解释这个概念:它们通常具有阴影"渐变,即基于 Button 颜色角色,但背景并非完全em>那种颜色.在下图中,我展示了一个按钮,我为 Button 角色设置了纯红色 (#ff0000) 颜色,但正如您所见,它不是红色:

This concept is better explained if you think about buttons: they often have a "shade" gradient, that is based on the Button color role, but the background is not exactly that color. In the following image, I'm showing a button for which I set a plain red (#ff0000) color for the Button role, but, as you can see, it's not red:

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

The palette colors are, in fact, a reference.

有些widget对其绘画行为没有特定的作用,由风格决定使用哪个角色以及如何使用,这就是QTabWidget的情况.在 Linux 上,默认样式通常是Fusion",它使用 Button 角色来绘制选项卡小部件的背景,但是当绘制该背景时,基于该颜色的渐变使用 em> 代替.同样,为 Button 角色(也就是标签小部件背景)应用了全红色,这不是真正的红色:

Some widgets don't have a specific role for their painting behavior, and it's up to the style to decide which role use and how, and that's the case of QTabWidget. On Linux the default style is usually "Fusion", which uses the Button role to paint the background of the tab widget, but when that background is painted, a gradient based on that color is used instead. Again, a full red color applied for the Button role (aka, the tab widget background), that is not an actual red:

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

There are two possible solutions for this.

在处理 QTabWidget 时,"Oxygen" 样式似乎更符合父背景.

The "Oxygen" style seem to be more coherent with the parent background when dealing with QTabWidget.

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

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

To know what styles are installed on the system, just call QStyleFactory.keys(). Note that not all styles are available for every system. Usually, "Fusion" and "Windows" are available, which means that if you try to access the "Oxygen" style and it's not installed, the fallback style will be used instead.

你的标签没有使用样式表设置的背景的原因是因为样式(融合)仍然使用前面提到的应用于背景颜色的渐变,这是因为标签可以有不同的颜色它是否被选中(具体来说,如果选中则比背景更亮,如果未选中则更暗).
为避免这种情况,您需要为所有标签栏伪状态设置样式表.

The reason for your tab not using the background set by the stylesheet is due to the fact that the style (fusion) is still using the aforementioned gradient applied to the background color, and that's because the tab can have a different color whether it's selected or not (specifically, lighter than the background if selected, darker if not).
To avoid that, you need to set the stylesheet for all tabbar pseudo states.

    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))

这就是结果:

这篇关于如何使背景颜色与表单背景相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆