Home > other >  Setting a stylesheet on a vertical QT/PyQT/PySide tab widget?
Setting a stylesheet on a vertical QT/PyQT/PySide tab widget?

Time:12-08

I have a custom tab widget that set the text to be horizontal on a vertical tab, however, when I implement a style sheet to change the tab once it is selected, I get this:enter image description here

It should be a uniform box, just like the one here but rotated 90 degrees. I believe that I need a way to change it so that height changes width and width changes height as I define the tab in a stylesheet with a height and width however this stylesheet refers to a normal tab widget, not a custom vertical one.

Feel free to offer any advice on my current code, whether it be about the custom tab widget class or my actual class. I am relatively new to QT

This is all of my code:

from PySide2 import QtCore
from PySide2.QtWidgets import *
from PySide2.QtGui import *

class TabBar(QTabBar):
    def tabSizeHint(self, index):
        s = QTabBar.tabSizeHint(self, index)
        s.transpose()
        return s

    def paintEvent(self, event):
        painter = QStylePainter(self)
        opt = QStyleOptionTab()

        for i in range(self.count()):
            self.initStyleOption(opt, i)
            painter.drawControl(QStyle.CE_TabBarTabShape, opt)
            painter.save()

            s = opt.rect.size()
            s.transpose()
            r = QtCore.QRect(QtCore.QPoint(), s)
            r.moveCenter(opt.rect.center())
            opt.rect = r

            c = self.tabRect(i).center()
            painter.translate(c)
            painter.rotate(90)
            painter.translate(-c)
            painter.drawControl(QStyle.CE_TabBarTabLabel, opt)
            painter.restore()

class VerticalTabWidget(QTabWidget):
    def __init__(self, *args, **kwargs):
        QTabWidget.__init__(self, *args, **kwargs)
        self.setTabBar(TabBar())
        self.setTabPosition(QTabWidget.West)

class Widget1(QWidget):
    def __init__(self, parent=None):
        super(Widget1, self).__init__(parent)
        self.gui()

    def gui(self):
        self.w1 = self
        self.w1.setAutoFillBackground(True)
        self.w1.setWindowTitle("")
        self.w1.setFixedSize(780, 459)
        palette = self.w1.palette()
        palette.setColor(self.w1.backgroundRole(), QColor(223, 230, 233, 255))
        self.w1.setPalette(palette)
        self.w1.setCursor(QtCore.Qt.ArrowCursor)
        self.w1.setToolTip("")
        self.tab1 = VerticalTabWidget(self.w1)
        self.tab1.move(0, 0)
        self.tab1.resize(290, 460)
        self.tab1.setTabPosition(QTabWidget.West)
        palette = self.tab1.palette()
        palette.setColor(self.tab1.backgroundRole(), QColor(223, 230, 233, 255))
        self.tab1.setPalette(palette)
        self.tab1.setCursor(QtCore.Qt.ArrowCursor)
        self.tab1.setToolTip("")
        
        self.ta1 = QWidget(self.tab1)
        self.ta1.setAutoFillBackground(True)
        self.ta1.setWindowTitle("")
        self.ta1.move(0, 0)
        self.ta1.resize(263, 456)
        palette = self.ta1.palette()
        palette.setColor(self.ta1.backgroundRole(), QColor(223, 230, 233, 255))
        self.ta1.setPalette(palette)
        self.ta1.setCursor(QtCore.Qt.ArrowCursor)
        self.ta1.setToolTip("")
        self.tab1.addTab(self.ta1, "General")
        self.ta2 = QWidget(self.tab1)
        self.ta2.setAutoFillBackground(True)
        self.ta2.setWindowTitle("")
        self.ta2.move(0, 0)
        self.ta2.resize(263, 456)
        palette = self.ta2.palette()
        palette.setColor(self.ta2.backgroundRole(), QColor(223, 230, 233, 255))
        self.ta2.setPalette(palette)
        self.ta2.setCursor(QtCore.Qt.ArrowCursor)
        self.ta2.setToolTip("")
        self.tab1.addTab(self.ta2, "Advanced")
        self.ta3 = QWidget(self.tab1)
        self.ta3.setAutoFillBackground(True)
        self.ta3.setWindowTitle("")
        self.ta3.move(0, 0)
        self.ta3.resize(263, 446)
        palette = self.ta3.palette()
        palette.setColor(self.ta3.backgroundRole(), QColor(223, 230, 233, 255))
        self.ta3.setPalette(palette)
        self.ta3.setCursor(QtCore.Qt.ArrowCursor)
        self.ta3.setToolTip("")
        self.tab1.addTab(self.ta3, "Selected State")
        self.ta4 = QWidget(self.tab1)
        self.ta4.setAutoFillBackground(True)
        self.ta4.setWindowTitle("")
        self.ta4.move(0, 0)
        self.ta4.resize(263, 446)
        palette = self.ta4.palette()
        palette.setColor(self.ta4.backgroundRole(), QColor(223, 230, 233, 255))
        self.ta4.setPalette(palette)
        self.ta4.setCursor(QtCore.Qt.ArrowCursor)
        self.ta4.setToolTip("")
        self.tab1.addTab(self.ta4, "Hover States")
        self.ta5 = QWidget(self.tab1)
        self.ta5.setAutoFillBackground(True)
        self.ta5.setWindowTitle("")
        self.ta5.move(0, 0)
        self.ta5.resize(263, 446)
        palette = self.ta5.palette()
        palette.setColor(self.ta5.backgroundRole(), QColor(223, 230, 233, 255))
        self.ta5.setPalette(palette)
        self.ta5.setCursor(QtCore.Qt.ArrowCursor)
        self.ta5.setToolTip("")
        self.tab1.addTab(self.ta5, "Disabled State")
        self.ta6 = QWidget(self.tab1)
        self.ta6.setAutoFillBackground(True)
        self.ta6.setWindowTitle("")
        self.ta6.move(0, 0)
        self.ta6.resize(263, 456)
        palette = self.ta6.palette()
        palette.setColor(self.ta6.backgroundRole(), QColor(223, 230, 233, 255))
        self.ta6.setPalette(palette)
        self.ta6.setCursor(QtCore.Qt.ArrowCursor)
        self.ta6.setToolTip("")
        self.tab1.addTab(self.ta6, "Advanced States")
        self.group1 = QGroupBox(self.w1)
        self.group1.setAutoFillBackground(True)
        self.group1.setTitle("")
        self.group1.move(390, 120)
        self.group1.resize(280, 220)
        palette = self.group1.palette()
        palette.setColor(self.group1.backgroundRole(), QColor(238, 238, 238, 255))
        self.group1.setPalette(palette)
        self.group1.setCursor(QtCore.Qt.ArrowCursor)
        self.group1.setToolTip("")
        self.button1 = QToolButton(self.group1)
        self.button1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.button1.setText("Preview Button")
        self.button1.move(80, 90)
        self.button1.resize(120, 40)
        self.button1.setCursor(QtCore.Qt.ArrowCursor)
        self.button1.setToolTip("")
        self.tab1.setStyleSheet("""

QTabBar{
  background-color:#dfe6e9;
}

QTabBar::tab:selected {
  background-color: #123456;
}

QTabBar::tab {
height: 100px; width: 70px;border: 2px;
}
""")
        return self.w1

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    a = Widget1()
    a.show()
    sys.exit(app.exec_())

CodePudding user response:

You are complicating things.

Translating the sizes just makes it all confusing, because the tab painting follows the size provided by the style (which you forced as 70x100, not 100x70).

Also, forcing the size of the tab is problematic, and since you're using the original (vertical) option for drawing, this will potentially clip (or overflow) the tab text, since you transposed the rectangle, so you should remove the width and height properties from the style sheet.

The solution is to minimize the transposition, and use the style option features to properly draw the contents, specifically setting the shape to a horizontal one so that the label is properly drawn.

class TabBar(QTabBar):
    def tabSizeHint(self, index):
        hint = super().tabSizeHint(index).transposed()
        return QSize(
            max(hint.width(), 100), 
            max(hint.height(), 70)
        )

    def paintEvent(self, event):
        painter = QStylePainter(self)
        opt = QStyleOptionTab()

        current = self.currentIndex()
        for i in range(self.count()):
            if i == current:
                continue
            self.initStyleOption(opt, i)
            painter.drawControl(QStyle.CE_TabBarTabShape, opt)
            opt.shape = QTabBar.RoundedNorth
            painter.drawControl(QStyle.CE_TabBarTabLabel, opt)

        self.initStyleOption(opt, current)
        painter.drawControl(QStyle.CE_TabBarTabShape, opt)
        opt.shape = QTabBar.RoundedNorth
        painter.drawControl(QStyle.CE_TabBarTabLabel, opt)

Notes:

  • the current tab is always painted above the others;
  • learn to use layout managers instead of fixed geometries;
  • always provide a minimal reproducible example: 99% of the contents of gui() is completely useless for the scope of the question;
  • Related