Изменить цвет вкладки QTabWidget

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

Вот небольшое демонстрационное приложение, иллюстрирующее мою проблему:

from PyQt4 import QtGui 

import sys

class coloredTabBar(QtGui.QTabBar):
    def __init__(self, parent = None):
        QtGui.QTabBar.__init__(self, parent)

    def paintEvent(self, event):
        p = QtGui.QStylePainter(self)
        painter = QtGui.QPainter(self)
        for index in range(self.count()): #for all tabs
            tab = QtGui.QStyleOptionTabV3() #create styled tab
            self.initStyleOption(tab, index) #initialize with default values
            #change background color to red
            tab.palette.setColor(QtGui.QPalette.Base, QtGui.QColor(255, 0, 0)) 
            p.drawControl(QtGui.QStyle.CE_TabBarTab, tab) #draw tab


class coloredTabWidget(QtGui.QTabWidget):
    def __init__(self, parent = None):
        QtGui.QTabWidget.__init__(self, parent)

        coloredTabs = coloredTabBar()
        self.setTabBar(coloredTabs) #replace default tabBar with my own implementation

if __name__ == "__main__":     
    app = QtGui.QApplication(sys.argv)

    tabWidget = coloredTabWidget()

    tabWidget.addTab(QtGui.QWidget(), "Hello")
    tabWidget.addTab(QtGui.QWidget(), "World")

    tabWidget.show()

    sys.exit(app.exec_())

С уважением

Бернхард


person user2494129    schedule 23.03.2014    source источник


Ответы (2)


Ладно, думаю, у меня кое-что есть. Это не самая красивая вещь, но она делает свое дело.

Если у кого-то есть лучшее представление о том, как решить эту проблему... дайте мне знать.

from PyQt4 import QtGui 
from PyQt4 import QtCore

import sys

class coloredTabBar(QtGui.QTabBar):
    def __init__(self, parent = None):
        QtGui.QTabBar.__init__(self, parent)

    def paintEvent(self, event):
        p = QtGui.QStylePainter(self)
        painter = QtGui.QPainter(self)
        painter.save()
        for index in range(self.count()): #for all tabs

            tabRect = self.tabRect(index)
            tabRect.adjust(-1, 3, -1, -1) #ajust size of every tab (make it smaller)
            if index == 0: #make first tab red 
                color = QtGui.QColor(255, 0, 0)
            elif index == 1: #make second tab yellow
                color = QtGui.QColor(255, 255, 0)
            else: #make all other tabs blue
                color = QtGui.QColor(0, 0, 255)
            if index == self.currentIndex(): #if it's the selected tab
                color = color.lighter(130) #highlight the selected tab with a 30% lighter color
                tabRect.adjust(0, -3, 0, 1) #increase height of selected tab and remove bottom border


            brush = QtGui.QBrush(color)
            painter.fillRect(tabRect, brush)

            painter.setPen(QtGui.QPen(QtGui.QColor(QtCore.Qt.black))) #black pen (for drawing the text)
            painter.drawText(tabRect, QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter,
                             self.tabText(index))

            painter.setPen(QtGui.QPen(QtGui.QColor(QtCore.Qt.gray))) #gray pen (for drawing the border)
            painter.drawRect(tabRect)
        painter.restore()

class coloredTabWidget(QtGui.QTabWidget):
    def __init__(self, parent = None):
        QtGui.QTabWidget.__init__(self, parent)

        coloredTabs = coloredTabBar()
        self.setTabBar(coloredTabs) #replace default tabBar with my own implementation

if __name__ == "__main__":     
    app = QtGui.QApplication(sys.argv)

    tabWidget = coloredTabWidget()

    tabWidget.addTab(QtGui.QWidget(), "Tab 1")
    tabWidget.addTab(QtGui.QWidget(), "Tab 2")
    tabWidget.addTab(QtGui.QWidget(), "Tab 3")
    tabWidget.addTab(QtGui.QWidget(), "Tab 4")

    tabWidget.show()

    sys.exit(app.exec_())
person user2494129    schedule 24.03.2014

Вы используете неправильную роль палитры. Вам нужен QPalette.Window, который является общим цветом фона виджета, а не QPalette.Base, который используется для более специализированных элементов, таких как элементы управления редактированием:

tab.palette.setColor(QtGui.QPalette.Window, QtGui.QColor(255, 0, 0))

Однако вы должны знать, что рисование вкладок таким образом не будет работать на всех платформах. Это связано с тем, что некоторые стили Windows и Mac используют растровые изображения при рисовании вкладок и поэтому не учитывают изменения палитры. Дополнительные сведения см. в Qt FAQ.

person ekhumoro    schedule 23.03.2014
comment
Спасибо за Ваш ответ! Я попробовал несколько разных ролей палитры (включая QPalette.Window), но на моей машине (Windows 7) это не имело значения. Я также думал об использовании QProxyStyle, но кажется, что этот модуль не включен в PyQt... Кажется, у вас большой опыт работы с Py(Qt)... как бы вы решили эту проблему? - person user2494129; 24.03.2014
comment
@user2494129. Боюсь, мне нечего добавить, чего еще нет в FAQ по Qt. В последний раз, когда я смотрел на это, единственным жизнеспособным вариантом в Windows было использование таблицы стилей. Но вы не можете стилизовать отдельные вкладки таким образом (все вкладки окрашены одинаково), и я думаю, что это может повлиять на другие аспекты стиля вкладок. Так что это не идеальное решение. - person ekhumoro; 24.03.2014
comment
Нет проблем, вы уже очень помогли мне с Qt FAQ! Я думаю, что попытаюсь сделать низкоуровневое рисование с помощью QPainter... Я не знаю, сработает ли это, но я думаю, что стоит попробовать. - person user2494129; 24.03.2014