2
votes

I want to customize a QTabWidget, so that every tab has it's own background color. I know, that this cannot be done with stylesheets, so I subclassed QTabBar and changed it's paintEvent. Then, I replaced the default QTabBar of QTabWidget with my own implementation. However, the background color of the tabs doesn't change. Does anybody know what I am missing?

Here is a small demo application which illustrates my problem:

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

Kind Regards

Bernhard

2

2 Answers

1
votes

Okay, I think I got something. It is not the prettiest thing, but it does the trick.

If anyone has a better idea on how to solve this problem...let me know.

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_())
1
votes

You're using the wrong palette role. You need QPalette.Window, which is the general widget background color, rather than QPalette.Base, which is for more specialized elements like edit-controls:

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

However, you should be aware that painting tabs in this way won't work on all platforms. This is because some Windows and Mac styles use pixmaps when drawing the tabs, and so don't take palette changes into account. See this Qt FAQ for more details.