PyQt4:如何分别为 QTabWidget 中的每个选项卡着色?

PyQt4: How to color each tab in QTabWidget separately?

我正在开发一个带有 GUI 的项目,为此我使用 Python 和 PyQt4 模块。

这是我的演示代码:

import sys
from PyQt4 import QtGui, QtCore

class Window(QtGui.QMainWindow):

    def __init__(self):
        super(Window, self).__init__()
        self.setWindowTitle('PyQt4 demo')
        self.setGeometry(50, 50, 1000, 1000)
        self.createTabs()
        self.styleTabs()
        self.show()

    def createTabs(self):
        '''Creates a QTabWidget with 5 tabs,
        named 1, 2, 3, 4, 5
        '''

        self.tabs = QtGui.QTabWidget(self)
        self.tabs.resize(1000, 1000)

        contents1 = QtGui.QWidget()
        contents2 = QtGui.QWidget()
        contents3 = QtGui.QWidget()
        contents4 = QtGui.QWidget()
        contents5 = QtGui.QWidget()

        self.tabs.addTab(contents1, '1')
        self.tabs.addTab(contents2, '2')
        self.tabs.addTab(contents3, '3')
        self.tabs.addTab(contents4, '4')
        self.tabs.addTab(contents5, '5')

    def styleTabs(self):
        #Would like to add some code here which colors
        #each tab with a different color.
        pass


def run():
    app = QtGui.QApplication(sys.argv)
    GUI = Window()
    sys.exit(app.exec_())

run()

大多数对象(包括 QtabWidget 和 QTabBar)使用 .setStyleSheet(str) 方法支持 CSS 样式。但是有了这个我只能用相同的颜色为所有选项卡着色。我还找到了一种方法来为选定的第一个、最后一个选项卡着色,但永远无法为 ex.: 索引为 2 的选项卡着色。

例如:

self.tabs.setStyleSheet('''
    QTabBar::tab {background-color: green;}
    QTabBar::tab:selected {background-color: red;}
    QTabBar::tab:first {background-color: red;}
    QTabBar::tab:last {background-color: red;}
    ''')

我也试过给当前的 QTabBar 应用颜色。这适用于 Qt,但显然不适用于 PyQt:

tab = self.tabs.tabBar()
tab.setStyleSheet('background-color: grey;')

PyQt4 着色方法也不行:

plt = QtGui.QPalette()
clr = QtGui.QColor()
clr.setRgb(100, 100, 100)
plt.setColor(10, clr)
tab.setPalette(plt)

我在网上搜索了很多次,但没有找到解决这个问题的方法。在这一点上,我什至不确定是否存在简单的解决方案。

有没有办法修改 PyQt4 源代码,以便应用上述技术之一?

附加信息:

不幸的是,QTabBar 没有公开它的所有属性,因为它的内容不是以正常方式布局的子部件,而是使用私有方法在内部绘制的。

虽然有两种可能性。

  1. 使用其 paintEvent 手动绘制标签栏。使用 QStyle draw* 方法,可以根据需要自定义它,同时与当前主题保持一致;这不是一件容易的事,但可以做到。

  2. 只自定义当前选中标签的背景:使用QTabBar的currentChanged信号,每次当前索引改变时你可以很容易地重置样式表

这是一个例子:

def createTabs(self):
    #[create your tabs, then...]
    self.tabColors = {
        0: 'green', 
        1: 'red', 
        2: 'yellow', 
        3: 'orange', 
        4: 'blue', 
        }
    self.tabs.tabBar().currentChanged.connect(self.styleTabs)

[...]

def styleTabs(self, index):
    self.tabs.setStyleSheet('''
        QTabBar::tab {{}}
        QTabBar::tab:selected {{background-color: {color};}}
        '''.format(color=self.tabColors[index]))

您可能希望在首次显示小部件时通过调用 styleTabs(0) "initialize" 它,因为只有在触发信号时才应用着色。