Changing color of individual tabs

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Changing color of individual tabs

kristof.mulier
Dear PyQt5 users/developers,

I've been struggeling with the following problem: I can't change the color of an individual tab (from a QTabWidget) without losing its stylesheet or burning up my CPU. I've posted the question some weeks ago on StackOverflow - but couldn't get a meaningful answer either.
Please take a look at the question, and win the +50 bonus points if you can help me out:


Thank you so much.

Kind greetings,

Kristof Mulier

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Changing color of individual tabs

Maurizio Berti
I just posted an answer, but I'll share it here too because it might be useful for people not on stackoverflow.



I stumbled upon similar issues some weeks ago, and then I studied a bit about how QStyle works. The concept is that you will let Qt draw the whole widget, but using QStyleOption helper classes (there's almost one for every kind of widget).enter image description here

Here's a simple example, without stylesheets. As you can see, it has some issues (the colored tab doesn't draw well when focused) and usually qpalette doesn't work well with stylesheets, but at least that's a start.

I tested it and it works without consuming resources. I hope it helps.

class TabBar(QtWidgets.QTabBar):
    def __init__(self, parent):
        QtWidgets.QTabBar.__init__(self, parent)
        self.colorIndexes = parent.colorIndexes

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        for index in range(self.count()):
            option = QtWidgets.QStyleOptionTab()
            self.initStyleOption(option, index)
            if index in self.colorIndexes:
                palette = self.palette()
                palette.setColor(palette.Window, self.colorIndexes[index])
                option.palette = palette
            self.style().drawControl(QtWidgets.QStyle.CE_TabBarTab, option, qp, self)

class TabWidget(QtWidgets.QTabWidget):
    def __init__(self):
        QtWidgets.QTabWidget.__init__(self)
        self.colorIndexes = {
            1: QtGui.QColor(QtCore.Qt.red), 
            3: QtGui.QColor(QtCore.Qt.blue), 
            }
        self.setTabBar(TabBar(self))
        for i in range(5):
            w = QtWidgets.QWidget()
            self.addTab(w, 'tab {}'.format(i))

Let me know what do you think of it! :-)

Regards,
Maurizio

2018-04-10 18:16 GMT+02:00 <[hidden email]>:
Dear PyQt5 users/developers,

I've been struggeling with the following problem: I can't change the color of an individual tab (from a QTabWidget) without losing its stylesheet or burning up my CPU. I've posted the question some weeks ago on StackOverflow - but couldn't get a meaningful answer either.
Please take a look at the question, and win the +50 bonus points if you can help me out:


Thank you so much.

Kind greetings,

Kristof Mulier

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt



--
È difficile avere una convinzione precisa quando si parla delle ragioni del cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Changing color of individual tabs

kristof.mulier
Hi Maurizio,

Thank you very much for the efforts you did to share your solution with us.
I have implemented your solution in my own sample code. You can see the result in a new chapter in the StackOverflow question: Second proposed solution. Yes, the question got so long (because I try to give as much information about the subject as possible) that I've divided it into chapters ;-)

Unfortunately, my stylesheet somehow gets in the way and turns the tabs back to the standard color. Only a thin colored line on the edge remains.

Throwing away my stylesheet is not really an option, unless there is another way to implement the styles from that stylesheet.


Van: "Maurizio Berti" <[hidden email]>
Aan: "kristof mulier" <[hidden email]>
Cc: "pyqt" <[hidden email]>
Verzonden: Woensdag 11 april 2018 12:20:49
Onderwerp: Re: [PyQt] Changing color of individual tabs

I just posted an answer, but I'll share it here too because it might be useful for people not on stackoverflow.



I stumbled upon similar issues some weeks ago, and then I studied a bit about how QStyle works. The concept is that you will let Qt draw the whole widget, but using QStyleOption helper classes (there's almost one for every kind of widget).enter image description here

Here's a simple example, without stylesheets. As you can see, it has some issues (the colored tab doesn't draw well when focused) and usually qpalette doesn't work well with stylesheets, but at least that's a start.

I tested it and it works without consuming resources. I hope it helps.

class TabBar(QtWidgets.QTabBar):
    def __init__(self, parent):
        QtWidgets.QTabBar.__init__(self, parent)
        self.colorIndexes = parent.colorIndexes

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        for index in range(self.count()):
            option = QtWidgets.QStyleOptionTab()
            self.initStyleOption(option, index)
            if index in self.colorIndexes:
                palette = self.palette()
                palette.setColor(palette.Window, self.colorIndexes[index])
                option.palette = palette
            self.style().drawControl(QtWidgets.QStyle.CE_TabBarTab, option, qp, self)

class TabWidget(QtWidgets.QTabWidget):
    def __init__(self):
        QtWidgets.QTabWidget.__init__(self)
        self.colorIndexes = {
            1: QtGui.QColor(QtCore.Qt.red), 
            3: QtGui.QColor(QtCore.Qt.blue), 
            }
        self.setTabBar(TabBar(self))
        for i in range(5):
            w = QtWidgets.QWidget()
            self.addTab(w, 'tab {}'.format(i))

Let me know what do you think of it! :-)

Regards,
Maurizio

2018-04-10 18:16 GMT+02:00 <[hidden email]>:
Dear PyQt5 users/developers,

I've been struggeling with the following problem: I can't change the color of an individual tab (from a QTabWidget) without losing its stylesheet or burning up my CPU. I've posted the question some weeks ago on StackOverflow - but couldn't get a meaningful answer either.
Please take a look at the question, and win the +50 bonus points if you can help me out:


Thank you so much.

Kind greetings,

Kristof Mulier

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt



--
È difficile avere una convinzione precisa quando si parla delle ragioni del cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net


_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Changing color of individual tabs

Maurizio Berti

Hello again, Kristof.
After more than a year, I stumbled upon your question once again for other reasons, but I had the opportunity to dig into QStyle much more in the meantime, so I've edited the answer I gave you, adding an alternate solution (which is a bit of a hack) that is much more consistent with the stylesheet. Still, it's not perfect yet, but I think I've got closer than ever... :-)
Here's the updated answer: https://stackoverflow.com/a/49772477

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt