Qt 绘制chrome风格Tab标签,且宽度适配文字内容

 参考 Qt绘制chrome风格的Tab标签_qt自定义绘制tab-优快云博客

在此对博主表示感谢。

#include <QApplication>
#include <QTabWidget>
#include <QProxyStyle>
#include <QStyleOption>
#include <QPainter>
#include <QPainterPath>

class CustomTabBarStyle : public QProxyStyle {
public:
    QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const override {
        QSize s = QProxyStyle::sizeFromContents(type, option, size, widget);
        if (type == QStyle::CT_TabBarTab) {
            // 设置最小宽度和最大宽度
            s.setWidth(qBound(48, s.width(), 220));
        }
        return s;
    }

    void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *w) const override
    {
        painter->save();
        painter->setPen(Qt::red);
        //    painter->drawRect(w->rect());
        painter->restore();
        switch (element) {
        case CE_TabBarTabLabel:
        {
            const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option);
            QRect textRect = subElementRect(QStyle::SE_TabBarTabText, tab, w);

            if (tab->state & QStyle::State_Selected) {
                painter->save();
                painter->setPen(QPen("#000000"));
                QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
                option.setWrapMode(QTextOption::NoWrap);
                painter->drawText(textRect, tab->text, option);
                painter->restore();
            }
            else if(tab->state & QStyle::State_MouseOver) {
                painter->save();
                painter->setPen(QPen("#000000"));
                QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
                option.setWrapMode(QTextOption::NoWrap);
                painter->drawText(textRect, tab->text, option);
                painter->restore();
            }
            else
            {
                painter->save();
                painter->setPen(QPen("#666666"));
                QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
                option.setWrapMode(QTextOption::NoWrap);
                painter->drawText(textRect, tab->text, option);
                painter->restore();
            }
        }
        break;
        case CE_TabBarTabShape:
        {
            const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option);
            // Set Anti-aliasing effect
            painter->setRenderHint(QPainter::Antialiasing);

            QRectF shapeRect = tab->rect;
            qreal arcLen = shapeRect.height() / 2;

            if (tab->state & QStyle::State_Selected) {
                painter->save();
                QPen pen(Qt::red);
                pen.setWidthF(0.5);
                painter->setPen(pen);
                //            painter->drawRect(shapeRect);
                painter->restore();

                painter->save();
                shapeRect.setX(shapeRect.x() - arcLen);
                shapeRect.setWidth(shapeRect.width() + arcLen *3/ 4);

                QPainterPath path;

                QRectF arcRect1(shapeRect.x(),
                                shapeRect.y() + shapeRect.height() / 3,
                                arcLen,
                                shapeRect.height() * 2 / 3);

                path.moveTo(QPointF(arcRect1.x(),
                                    arcRect1.y() + arcRect1.height()));

                path.lineTo(QPointF(arcRect1.x() + arcRect1.width() / 2,
                                    arcRect1.y() + arcRect1.height()));

                // Starting from 270°, returning to the arc of 90°
                path.arcTo(arcRect1, 270.0, 90.0);

                path.lineTo(QPointF(arcRect1.x() + arcRect1.width(),
                                    arcRect1.y()));

                QRectF arcRect2(shapeRect.x() + arcRect1.width(),
                                shapeRect.y(),
                                arcLen,
                                shapeRect.height() * 2 / 3);

                // Starting from 180°, returning to the arc of -90°
                path.arcTo(arcRect2, 180.0, -90.0);

                path.lineTo(QPointF(arcRect2.x() + shapeRect.width() -  2 * (arcRect2.x()  + arcRect2.width()) + arcRect2.width() / 2,
                                    arcRect2.y()));

                QRectF arcRect3(shapeRect.x() + shapeRect.width() - 2 * arcRect1.width(),
                                shapeRect.y(),
                                arcRect1.width(),
                                shapeRect.height() * 2 / 3);

                path.arcTo(arcRect3, 90.0, -90.0);

                path.lineTo(QPointF(arcRect3.x() + arcRect3.width(),
                                    arcRect3.y() + arcRect3.height()));

                QRectF arcRect4(arcRect3.x() + arcRect3.width(),
                                arcRect3.y() + arcRect3.height() / 2,
                                arcRect1.width(),
                                shapeRect.height() * 2 / 3);

                path.arcTo(arcRect4, 180.0, 90.0);

                path.lineTo(QPointF(arcRect1.x(),
                                    arcRect1.y() + arcRect1.height()));

                painter->setPen(Qt::NoPen);
                painter->setBrush(Qt::white);
                QPolygonF polygon = path.toFillPolygon();
                painter->drawPolygon(polygon);

                painter->restore();
            }else if(tab->state & QStyle::State_MouseOver)
            {
                //            return;
                painter->save();
                QPen pen(Qt::black);
                pen.setWidthF(0.5);
                painter->setPen(pen);
                //            painter->drawRect(shapeRect);
                painter->restore();
                painter->save();

                shapeRect.setX(shapeRect.x() - arcLen);
                shapeRect.setWidth(shapeRect.width() + arcLen *3/ 4);

                QPainterPath path;

                QRectF arcRect1(shapeRect.x(),
                                shapeRect.y() + shapeRect.height() / 3,
                                arcLen,
                                shapeRect.height() * 2 / 3);

                path.moveTo(QPointF(arcRect1.x(),
                                    arcRect1.y() + arcRect1.height()));

                path.lineTo(QPointF(arcRect1.x() + arcRect1.width() / 2,
                                    arcRect1.y() + arcRect1.height()));

                // Starting from 270°, returning to the arc of 90°
                path.arcTo(arcRect1, 270.0, 90.0);

                path.lineTo(QPointF(arcRect1.x() + arcRect1.width(),
                                    arcRect1.y()));

                QRectF arcRect2(shapeRect.x() + arcRect1.width(),
                                shapeRect.y(),
                                arcLen,
                                shapeRect.height() * 2 / 3);

                // Starting from 180°, returning to the arc of -90°
                path.arcTo(arcRect2, 180.0, -90.0);

                path.lineTo(QPointF(arcRect2.x() + shapeRect.width() -  2 * (arcRect2.x()  + arcRect2.width()) + arcRect2.width() / 2,
                                    arcRect2.y()));

                QRectF arcRect3(shapeRect.x() + shapeRect.width() - 2 * arcRect1.width(),
                                shapeRect.y(),
                                arcRect1.width(),
                                shapeRect.height() * 2 / 3);

                path.arcTo(arcRect3, 90.0, -90.0);

                path.lineTo(QPointF(arcRect3.x() + arcRect3.width(),
                                    arcRect3.y() + arcRect3.height()));

                QRectF arcRect4(arcRect3.x() + arcRect3.width(),
                                arcRect3.y() + arcRect3.height() / 2,
                                arcRect1.width(),
                                shapeRect.height() * 2 / 3);

                path.arcTo(arcRect4, 180.0, 90.0);

                path.lineTo(QPointF(arcRect1.x(),
                                    arcRect1.y() + arcRect1.height()));

                painter->setPen(Qt::NoPen);
                painter->setBrush(QColor("#FBFCFC"));
                QPolygonF polygon = path.toFillPolygon();
                painter->drawPolygon(polygon);

                painter->restore();

            }else
            {
                painter->save();

                shapeRect.setX(shapeRect.x() - arcLen);
                shapeRect.setWidth(shapeRect.width() + arcLen / 2);

                QPen pen(Qt::black);
                pen.setWidthF(0.5);
                painter->setPen(pen);

                /// Draw a dividing line on the left
                painter->drawLine(QPointF(shapeRect.x() + arcLen*2/3 -1, shapeRect.height() / 3),
                                  QPointF(shapeRect.x() + arcLen*2/3 -1, shapeRect.height() * 2 / 3));

                /// Draw a dividing line on the right
                //            painter->drawLine(baseR.x() + baseR.width() - arcLen,
                //                              baseR.height() / 4,
                //                              baseR.x() + baseR.width() - arcLen,
                //                              baseR.height() * 3 / 4);

                painter->restore();
            }
        }
        break;
        default:
            QProxyStyle::drawControl(element, option, painter, w);
            break;
        }
    }
};

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    QTabWidget tabWidget;
   
    // 添加几个标签页,部分标签页标题较长
    tabWidget.addTab(new QWidget(), "s");
    tabWidget.addTab(new QWidget(), "Tab 2 ①This is a very long title ②This is a very long title");
    tabWidget.addTab(new QWidget(), "Tab 3 Another long title");
    tabWidget.addTab(new QWidget(), "Tab 4 Short");
    tabWidget.addTab(new QWidget(), "Tab 5 Yet another long title");

    // 设置每个标签页可关闭
    tabWidget.tabBar()->setTabsClosable(true);
    tabWidget.tabBar()->setUsesScrollButtons(false);
    tabWidget.tabBar()->setElideMode(Qt::ElideRight);

    // 设置自定义样式
    CustomTabBarStyle customStyle;
    tabWidget.tabBar()->setStyle(&customStyle);

    // 连接关闭按钮信号
    QObject::connect(&tabWidget, &QTabWidget::tabCloseRequested, [&](int index) {
        tabWidget.removeTab(index);
    });

    tabWidget.show();
    return a.exec();
}

判断tab的索引:

// 获取 tab 索引
            auto tabBar = qobject_cast<const QTabBar*>(w);
            if (tabBar)
            {
                int index = tabBar->tabAt(tab->rect.topLeft());
                qDebug() << __FUNCTION__ << __LINE__ << index;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值