如何将 QTabBar 中的图标居中?

Posted

技术标签:

【中文标题】如何将 QTabBar 中的图标居中?【英文标题】:How can I center the icons in a QTabBar? 【发布时间】:2019-04-25 09:24:10 【问题描述】:

我正在尝试更改 QTabWidget 的样式。我想缩小每个选项卡中图标和文本之间的差距,并将两者居中。

这就是我现在拥有的:

这就是我想要的:

我当前的样式表是:

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 中添加一些填充,这有助于在图标左侧添加一些空间,但没有减少图标和文本之间的空间量。

【问题讨论】:

你能给我们可执行代码吗?我有很多错误,图标,颜色等等。 @user9402680 你清楚地看到你必须用颜色或rgb(x,y,z)的名称替换colors.xxx,例如将colors.light_gray更改为"gray"和@987654330 @到"darkgray" @eyllanesc 你是对的。我不妨这样做。 很抱歉,我将更改我的代码以使其尽可能易于运行。对于图标,任何 QIcon 都可以解决问题。 【参考方案1】:

一种可能的解决方案是使用 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)

【讨论】:

那行得通。我有点难过需要深入了解 qt 的低级机制;)我想现在我需要阅读QProxyStyle 的文档,除非很快提出更简单的解决方案。谢谢! @PiRK 很遗憾,Qt StyleSheet 是有限的,对于 QTabBar 图标,它不能被 QSS 修改。 这段代码能否在标签文本的中心但上方绘制图标?@eyllanesc @Ahmed4end 我的代码显然没有这样做,但您可以将其作为获得所需内容的起点。

以上是关于如何将 QTabBar 中的图标居中?的主要内容,如果未能解决你的问题,请参考以下文章

QTabBar 图标位置

如何将宽度设置为“填充父项”的android按钮中的图标和文本居中

如何将带有不均匀图标的文本居中对齐?

如何使 QStandardItemModel 中的图标居中?

在拆分的 Widget PyQt Qt 中,将 Tab 从 QtabBar 拖放到其他 QtabBar

如何使 QToolButton 中的图标居中?