#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();
}
![](https://i-blog.csdnimg.cn/direct/1cbaa25745bb4afd9753deeb1b630073.gif)
![](https://i-blog.csdnimg.cn/direct/ac4f18658def4bfdb225abd1173b18f9.png)