Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pyqt5 tabwidget vertical tab horizontal text alignment left

Since pyqt doesn't have horizontal text in vertical tab option, I followed this link to make it happen. I wanted to have icons on the left and then text after icon and different color for selected tab text, inactive tabs text. Below code gets it done almost. The only problem is text alignment is center. I tried changing tabRect.center() but changing it with left and top or right etc is making it crash.

The commented code which I got from this linkgets me left alignment but it didn't have icons which I added. But in that I am unable to change text color of inactive tabs.

I am new to python and I am unable to find a solution for this. I tried this as well link but this only sets background color. tried using this option as well setTabTextColor link but it didn't work for some reason. been trying from 2 days.

Whenever I try to set text color using stylesheet with commented code, the "color" option won't work in stylesheet. any ideas on how to get this done? thanks

from PyQt5 import QtCore, QtGui, QtWidgets

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

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

        for i in range(self.count()):
            self.initStyleOption(opt, i)
            painter.drawControl(QtWidgets.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(QtWidgets.QStyle.CE_TabBarTabLabel, opt)
            painter.restore()

        # for i in range(self.count()):
        #     self.initStyleOption(opt, i)
        #     c = self.tabRect(i)
        #     c.moveLeft(35)
        #     painter.drawControl(QtWidgets.QStyle.CE_TabBarTabShape, opt)
        #     # painter.setPen(QColor(255, 255, 255))
        #     painter.drawText(c, QtCore.Qt.AlignVCenter | QtCore.Qt.TextDontClip, self.tabText(i))
        #     if i == 0:
        #         painter.drawImage(QtCore.QRectF(8, 8, 20, 20), QtGui.QImage("images/logo.png"))
        #     if i == 1:
        #         painter.drawImage(QtCore.QRectF(8, 44, 20, 20), QtGui.QImage("images/data.png"))
        #     if i == 2:
        #         painter.drawImage(QtCore.QRectF(8, 82, 20, 20), QtGui.QImage("images/browse.png"))
        #     if i == 3:
        #         painter.drawImage(QtCore.QRectF(8, 120, 20, 20), QtGui.QImage("images/off.png"))
        #     if i == 4:
        #         painter.drawImage(QtCore.QRectF(8, 158, 20, 20), QtGui.QImage("images/cal.png"))
        #     if i == 5:
        #         painter.drawImage(QtCore.QRectF(8, 196, 20, 20), QtGui.QImage("images/fol.png"))
        #     if i == 6:
        #         painter.drawImage(QtCore.QRectF(8, 232, 20, 20), QtGui.QImage("images/exc.png"))
        # painter.end()


class TabWidget(QtWidgets.QTabWidget):
    def __init__(self, *args, **kwargs):
        QtWidgets.QTabWidget.__init__(self, *args, **kwargs)
        self.setTabBar(TabBar(self))
        self.setTabPosition(QtWidgets.QTabWidget.West)
like image 848
Deadlyxda Avatar asked Jul 18 '18 14:07

Deadlyxda


1 Answers

The solution is to use a QProxyStyle to redirect text painting:

from PyQt5 import QtCore, QtGui, QtWidgets


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

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

        for i in range(self.count()):
            self.initStyleOption(opt, i)
            painter.drawControl(QtWidgets.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(QtWidgets.QStyle.CE_TabBarTabLabel, opt);
            painter.restore()


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

class ProxyStyle(QtWidgets.QProxyStyle):
    def drawControl(self, element, opt, painter, widget):
        if element == QtWidgets.QStyle.CE_TabBarTabLabel:
            ic = self.pixelMetric(QtWidgets.QStyle.PM_TabBarIconSize)
            r = QtCore.QRect(opt.rect)
            w =  0 if opt.icon.isNull() else opt.rect.width() + self.pixelMetric(QtWidgets.QStyle.PM_TabBarIconSize)
            r.setHeight(opt.fontMetrics.width(opt.text) + w)
            r.moveBottom(opt.rect.bottom())
            opt.rect = r
        QtWidgets.QProxyStyle.drawControl(self, element, opt, painter, widget)

if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    QtWidgets.QApplication.setStyle(ProxyStyle())
    w = TabWidget()
    w.addTab(QtWidgets.QWidget(), QtGui.QIcon("zoom.png"), "ABC")
    w.addTab(QtWidgets.QWidget(), QtGui.QIcon("zoom-in.png"), "ABCDEFGH")
    w.addTab(QtWidgets.QWidget(), QtGui.QIcon("zoom-out.png"), "XYZ")

    w.resize(640, 480)
    w.show()

    sys.exit(app.exec_())

enter image description here

like image 179
eyllanesc Avatar answered Sep 21 '22 13:09

eyllanesc