Как сделать цвет фона таким же, как фон формы? - PullRequest
0 голосов
/ 12 февраля 2020

В 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:

enter image description here

Мой вопрос: как можно ли сделать фон QTabWidget того же цвета, что и фон формы (в данном случае QWidget)?

Некоторые вещи, которые я пробовал:

Многие виджеты имеют функцию, подобную этой :

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

Но в QTabWidget, похоже, нет setBackgroundBrush или эквивалента, который я могу найти.

Я нашел несколько сообщений, в которых предлагается использовать таблицы стилей для достижения этой цели, но Я не уверен, как это настроить. Нужно ли подклассу QTabWidget, чтобы достичь этого? Кроме того, как я могу получить цвет фона формы по умолчанию? Я мог бы использовать простое предположение и проверку, чтобы приблизиться, но затем он может немного измениться на разных платформах, так что это не особенно желательно.

--- Edit ---

Arrrrrrrggggggg !!! 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 на цвет фона формы по умолчанию, но не меняет цвет вкладки !!

enter image description here

1 Ответ

1 голос
/ 13 февраля 2020

Существует два возможных решения этой проблемы.

Основная причина такого поведения может быть найдена в используемом стиле .

Каждый стиль Qt решает, как цвета палитры используются для рисования виджета. Это означает, что даже если вы установите определенный c цвет для (скажем, фона), не гарантирует, что виджет будет иметь этот указанный c цвет фона.

Эту концепцию лучше объяснить, если подумать о кнопках: они часто имеют «градиент оттенка», который основан на роли цвета Button, но фон не является точно этим цветом. На следующем изображении я показываю кнопку, для которой я установил простой красный (# ff0000) цвет для роли кнопки, но, как вы можете видеть, это , а не красный:

a red button, not exactly red

Цвета палитры на самом деле являются справочными.

Некоторые виджеты не имеют определенной c роли для их поведения при рисовании, и именно стиль решает, какую роль использовать и как, и это в случае с QTabWidget. На Linux стилем по умолчанию обычно является «Fusion», который использует роль Button для рисования фона виджета со вкладками, но когда этот фон закрашивается, используется градиент на основе этого цвета вместо. Снова, полный красный цвет, примененный к роли Button (иначе, фон виджета со вкладками), который не является реальным красным:

a red tab, not exactly red

Для этого есть два возможных решения.

1. Используйте другой стиль

Стиль "Кислород" кажется более согласованным с родительским фоном при работе с QTabWidget.

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

oxygen style applied, with same background for tab widget contents

Чтобы узнать, какие стили установлены в системе, просто наберите QStyleFactory.keys(). Обратите внимание, что не все стили доступны для каждой системы. Обычно доступны «Fusion» и «Windows», что означает, что если вы попытаетесь получить доступ к стилю «Кислород», а он не установлен, вместо него будет использован запасной стиль.

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

И вот результат:

this is a cool tab widget

...