Как я могу центрировать иконки в QTabBar? - PullRequest
1 голос
/ 25 апреля 2019

Я пытаюсь изменить стиль для QTabWidget. Я хотел бы уменьшить разрыв между значком и текстом на каждой вкладке и центрировать обе.

Вот что у меня сейчас:

enter image description here

Вот что я хочу:

enter image description here

Моя текущая таблица стилей:

stylesheet = """
    QTabBar {
        background: %s;
    }

    QTabBar::tab {
        background: %s;
        height: 60px;
        width: 200px;
        font-family: Ubuntu;
        font-weight: bold;
        font-size: 14px;
        color: %s;
    }

    QTabBar::tab:selected {
        background: white;
    }

    QTabWidget {
        background: white;
    }

    QTabWidget::pane {
        background: white;
        border: none;
    }

    """ % (colors.light_gray,    # tabbar bg where there are no tabs
           colors.light_gray,    # tab bg
           colors.dark_gray,)    # text color

Значки заданы в коде:

class ImageProcessingPage(qt.QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setStyleSheet(stylesheet)

        layout = qt.QHBoxLayout()
        self.setLayout(layout)

        self.tabWidget = qt.QTabWidget()
        layout.addWidget(self.tabWidget)

        self.tabWidget.addTab(qt.QLabel("Placeholder for edition"),
                              icons.getQIcon("pic-edit-gray"),
                              "Edition")
        self.tabWidget.addTab(qt.QLabel("Placeholder for edition"),
                              icons.getQIcon("roi-gray"),
                              "ROI")
        self.tabWidget.addTab(qt.QLabel("Placeholder for edition"),
                              "Segmentation")

Я попытался добавить некоторые отступы к QTabBar::tab, который работал для добавления некоторого пространства слева от значка, но не уменьшал расстояние между значком и текстом.

1 Ответ

2 голосов
/ 26 апреля 2019

Возможное решение - использовать QProxyStyle, чтобы нарисовать значок в нужном вам месте:

from PyQt5 import QtCore, QtGui, QtWidgets


class TabBarStyle(QtWidgets.QProxyStyle):
    def drawControl(self, element, option, painter, widget=None):
        icon = QtGui.QIcon()
        if element == QtWidgets.QStyle.CE_TabBarTabLabel:
            icon = QtGui.QIcon(option.icon)
            # draw without icon
            option.icon = QtGui.QIcon()
        super(TabBarStyle, self).drawControl(element, option, painter, widget)
        if icon.isNull():
            return
        verticalTabs = option.shape in (
            QtWidgets.QTabBar.RoundedEast,
            QtWidgets.QTabBar.RoundedWest,
            QtWidgets.QTabBar.TriangularEast,
            QtWidgets.QTabBar.TriangularWest,
        )

        alignment = QtCore.Qt.AlignCenter | QtCore.Qt.TextShowMnemonic
        if not self.proxy().styleHint(
            QtWidgets.QStyle.SH_UnderlineShortcut, option, widget
        ):
            alignment |= QtCore.Qt.TextHideMnemonic

        if verticalTabs:
            painter.save()
            if option.shape in (
                QtWidgets.QTabBar.RoundedEast,
                QtWidgets.QTabBar.TriangularEast,
            ):
                newX = tr.width() + tr.x()
                newY = tr.y()
                newRot = 90
            else:
                newX = tr.x()
                newY = tr.y() + tr.height()
                newRot = -90
            m = QtCore.QTransform.fromTranslate(newX, newY)
            m.rotate(newRot)
            p.setTransform(m, True)
        tr = self.proxy().subElementRect(
            QtWidgets.QStyle.SE_TabBarTabText, option, widget
        )
        fm = QtGui.QFontMetrics(painter.font())
        iconRect = fm.boundingRect(option.text)
        iconSize = QtCore.QSize(option.iconSize)
        if not iconSize.isValid():
            iconExtent = self.proxy().pixelMetric(
                QtWidgets.QStyle.PM_SmallIconSize
            )
            iconSize = QtCore.QSize(iconExtent, iconExtent)
            tabIconSize = icon.actualSize(
                iconSize,
                QtGui.QIcon.Normal
                if (option.state & QtWidgets.QStyle.State_Enabled)
                else QtGui.QIcon.Disabled,
                QtGui.QIcon.On
                if (option.state & QtWidgets.QStyle.State_Selected)
                else QtGui.QIcon.Off,
            )
            # High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize
            iconSize = QtCore.QSize(
                min(tabIconSize.width(), iconSize.width()),
                min(tabIconSize.height(), iconSize.height()),
            )
        offset = 10
        iconRect.moveCenter(
            tr.center() - QtCore.QPoint(iconSize.width() + offset, 0)
        )
        tabIcon = icon.pixmap(
            widget.window().windowHandle() if widget else None,
            option.iconSize,
            QtGui.QIcon.Normal
            if (option.state & QtWidgets.QStyle.State_Enabled)
            else QtGui.QIcon.Disabled,
            QtGui.QIcon.On
            if (option.state & QtWidgets.QStyle.State_Selected)
            else QtGui.QIcon.Off,
        )
        painter.drawPixmap(iconRect.x(), iconRect.y(), tabIcon)
        if verticalTabs:
            painter.restore()

И затем вы установите его в QTabBar:

self.tabbar_style = TabBarStyle(self.tabWidget.tabBar().style())
self.tabWidget.tabBar().setStyle(self.tabbar_style)

enter image description here

...