Qt编写自定义控件:直角梯形形状的QTabBar

#ifndef RIGHTANGLEDTRAPEZOIDTABBAR_H
#define RIGHTANGLEDTRAPEZOIDTABBAR_H

#include <QTabBar>
#include <QPainterPath>

class RightAngledTrapezoidTabBar : public QTabBar
{
    Q_OBJECT
public:
    explicit RightAngledTrapezoidTabBar(QWidget *parent = 0);

protected:
    QSize tabSizeHint(int index) const override;
    void paintEvent(QPaintEvent *event)override;
    void mouseMoveEvent(QMouseEvent *event)override;
    void enterEvent(QEvent *event)override;
    void leaveEvent(QEvent *event)override;
    void mousePressEvent(QMouseEvent *event)override;
    void resizeEvent(QResizeEvent *event)override;

private:
    void updatePath();
    bool isEnter{false};
    QList<QPainterPath> pathList;
};

#endif // RIGHTANGLEDTRAPEZOIDTABBAR_H
#include "rightangledtrapezoidtabbar.h"
#include <QPainter>
#include <QStyleOptionTabV4>
#include <QMouseEvent>

RightAngledTrapezoidTabBar::RightAngledTrapezoidTabBar(QWidget *parent)
    : QTabBar(parent)
{
    setMouseTracking(true);
    // setUsesScrollButtons(false);
    connect(this,&QTabBar::currentChanged,this,qOverload<>(&QWidget::update));
}

QSize RightAngledTrapezoidTabBar::tabSizeHint(int index) const
{
    // return QTabBar::tabSizeHint(index);
    // return QSize(QTabBar::tabSizeHint(index).width()*1.5,50);
    // return QTabBar::tabSizeHint(index) * 1.5;
    return QSize(QTabBar::tabSizeHint(index).width()*1.5,40);
}

void RightAngledTrapezoidTabBar::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing,true);
    auto current = this->currentIndex();

    /*
    W = w×c - (w×(c-1))×0.25
    ->
    w = W / (0.75c+0.25)

    width() = w * count() - (w * (count()-1)) * 0.25;
    */
    int size = sizeHint().width() / (0.75 * count() + 0.25);

    QStyleOptionTabV4 option;
    QColor brush;
    QColor textColor;
    for(int i = 0 ; i < count(); ++i)
    {
        if(i == current)
        {
            continue;
        }

        auto boundingRect = tabRect(i);
        boundingRect = QRect(size * 0.75 * i,
                             0,
                             size,
                             boundingRect.height());

        initStyleOption(&option, i);

        if(isEnter && (QStyle::State_MouseOver & option.state))
        {
            brush = QColor(0xe1e1e1);
            textColor = Qt::black;
        }
        else if(QStyle::State_Selected & option.state)
        {
            brush = QColor(0xf5f6f7);
            textColor = QColor(0xa4a0a0);
        }
        else
        {
            brush = QColor(0xf5f6f7);
            textColor = QColor(0xa4a0a0);
        }

        auto thisTimePath = pathList.at(i);
        if(current > i)
        {
            if(i < (count() - 1))
            {
                auto differenceSet = pathList.at(i + 1) - thisTimePath;
                thisTimePath = thisTimePath - differenceSet;
            }
        }
        else
        {
            if(i != 0)
            {
                thisTimePath = thisTimePath - pathList.at(i - 1);
            }
        }

        painter.setBrush(brush);
        painter.setClipPath(thisTimePath);
        painter.setPen(Qt::black);
        painter.drawPath(thisTimePath);

        painter.setBrush(Qt::transparent);
        painter.setPen(textColor);
        painter.drawText(boundingRect.adjusted(0,0,-boundingRect.width() * 0.3,0),Qt::AlignCenter,tabText(i));
    }

    {
        auto boundingRect = tabRect(current);
        boundingRect = QRect(size * 0.75 * current,
                             0,
                             size,
                             boundingRect.height() + 1);

        QPainterPath boundingRectPath;
        boundingRectPath.addRoundedRect(boundingRect,6,6);

        QPainterPath halfRectPath;
        halfRectPath.addRect(QRect(boundingRect.x(),
                                   boundingRect.y() + boundingRect.height() / 2,
                                   boundingRect.width(),
                                   boundingRect.height() / 2 + 2));

        boundingRectPath = boundingRectPath + halfRectPath;

        QPolygonF trianglePolygon;
        trianglePolygon.append(boundingRect.topRight() + QPoint(2,0));
        trianglePolygon.append(boundingRect.bottomRight() + QPoint(2,6));
        trianglePolygon.append(boundingRect.topLeft() + QPoint(boundingRect.width() * 0.6,0));

        QPainterPath trianglePath;
        trianglePath.addPolygon(trianglePolygon);

        auto currentPath = boundingRectPath - trianglePath;

        painter.setClipPath(currentPath);
        painter.setPen(Qt::black);
        painter.setBrush(QColor(0xf5f6f7));
        painter.drawPath(currentPath);

        painter.setBrush(Qt::transparent);
        painter.setPen(Qt::black);
        painter.drawText(boundingRect.adjusted(0,0,-boundingRect.width() * 0.3,0),Qt::AlignCenter,tabText(current));
    }
}

void RightAngledTrapezoidTabBar::mouseMoveEvent(QMouseEvent *event)
{
    update();
    QTabBar::mouseMoveEvent(event);
}

void RightAngledTrapezoidTabBar::enterEvent(QEvent *event)
{
    isEnter = true;
    update();
    QTabBar::enterEvent(event);
}

void RightAngledTrapezoidTabBar::leaveEvent(QEvent *event)
{
    isEnter = false;
    update();
    QTabBar::leaveEvent(event);
}

void RightAngledTrapezoidTabBar::mousePressEvent(QMouseEvent *event)
{
    QTabBar::mousePressEvent(event);
    auto pos = event->pos();
    for(int i = 0;i < pathList.size();++i)
    {
        if(pathList.at(i).contains(pos))
        {
            if(currentIndex() != i)
            {
                setCurrentIndex(i);
                update();
                break;
            }
        }
    }
}

void RightAngledTrapezoidTabBar::resizeEvent(QResizeEvent *event)
{
    updatePath();
    QTabBar::resizeEvent(event);
}

void RightAngledTrapezoidTabBar::updatePath()
{
    pathList.clear();

    int size = sizeHint().width() / (0.75 * count() + 0.25);

    for(int i = 0 ; i < count(); ++i)
    {
        auto rect = tabRect(i);
        auto boundingRect = QRect(size * 0.75 * i,
                                  0,
                                  size,
                                  rect.height());

        QPainterPath boundingRectPath;
        boundingRectPath.addRoundedRect(boundingRect,6,6);

        QPolygonF trianglePolygon;//三角形
        trianglePolygon.append(boundingRect.topRight() + QPoint(2,0));
        trianglePolygon.append(boundingRect.bottomRight() + QPoint(2,6));
        trianglePolygon.append(boundingRect.topLeft() + QPoint(boundingRect.width() * 0.6,0));

        QPainterPath trianglePath;
        trianglePath.addPolygon(trianglePolygon);

        pathList << boundingRectPath - trianglePath;
    }
}
#ifndef RIGHTANGLEDTRAPEZOIDTABBARTABWIDGET_H
#define RIGHTANGLEDTRAPEZOIDTABBARTABWIDGET_H

#include <QTabWidget>

class RightAngledTrapezoidTabBarTabWidget : public QTabWidget
{
    Q_OBJECT
public:
    explicit RightAngledTrapezoidTabBarTabWidget(QWidget *parent = 0);
};

#endif // RIGHTANGLEDTRAPEZOIDTABBARTABWIDGET_H
#include "rightangledtrapezoidtabbartabwidget.h"
#include "rightangledtrapezoidtabbar.h"

RightAngledTrapezoidTabBarTabWidget::RightAngledTrapezoidTabBarTabWidget(QWidget *parent)
{
    setTabBar(new RightAngledTrapezoidTabBar(this));
}
#include "rightangledtrapezoidtabbartabwidget.h"

#include <QApplication>

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

    RightAngledTrapezoidTabBarTabWidget w2;

    w2.addTab(new QWidget,"");
    w2.addTab(new QWidget,"");
    w2.addTab(new QWidget,"");
    w2.addTab(new QWidget,"");
    w2.addTab(new QWidget,"");
    w2.addTab(new QWidget,"");
    w2.addTab(new QWidget,"");
    w2.addTab(new QWidget,"");

    for(int i = 0;i < w2.count();++i)
    {
        w2.setTabText(i,QString("测试%1").arg(i+1));
    }
    w2.setCurrentIndex(0);

    w2.show();
    w2.resize(1000,400);

    return a.exec();
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值