element.ui-Qt实现之Tabs动画滚动
阅读原文时间:2021年04月23日阅读:1

视觉和交互参考前端element组件,使用Qt实现
element的Tabs效果
打算使用最简单的方式实现可滑动的Tabs,继承于QTabWidget,加入些动画效果绘制下划线就搞定了,是不是很简单。
没有截动态效果,可自己调试

但是其中也有些注意点,这里也是阅读qtabwidget.cpp和qstylesheetstyle.cpp源码解决

.h文件

#include <QTabWidget>
#include <QVariantAnimation>

class TabBarAnimation;
class QSimpleSliderNavigation : public QTabWidget
{
    Q_OBJECT

public:
    QSimpleSliderNavigation(QWidget *parent = Q_NULLPTR);
    ~QSimpleSliderNavigation();
    void setAnimationCurrentValue(int value);
protected:
    void paintEvent(QPaintEvent *);
    bool eventFilter(QObject *o, QEvent *e);
private:
    void startAnimation(int beginX,int endX,int duration); // 先只考虑横向的
private:
    TabBarAnimation *animation;
    int m_animationX;
};

.cpp部分

#include "QSimpleSliderNavigation.h"
#include <QStyleOptionTabWidgetFrame>
#include <QStylePainter>
#include <QMouseEvent>


struct TabBarAnimation : public QVariantAnimation {
    TabBarAnimation(QSimpleSliderNavigation* t) : tabs(t)
    {
        setEasingCurve(QEasingCurve::InOutQuad);
    }
    void updateCurrentValue(const QVariant &current) Q_DECL_OVERRIDE;
private:
    QSimpleSliderNavigation* tabs;
};

void TabBarAnimation::updateCurrentValue(const QVariant &current)
{
    if (tabs)
    {
        tabs->setAnimationCurrentValue(current.toInt());
    }
}

//这里的 QTabWidget::pane {border: none;position: relative;top:2px;} 很重要,将pane的位置下移,这样绘制的下划线才能显示
QSimpleSliderNavigation::QSimpleSliderNavigation(QWidget *parent)
    : QTabWidget(parent)
{
    setStyleSheet("QTabWidget {background-color: rgb(238, 243, 250);} \
                  QTabWidget::pane {border: none;position: relative;top:2px;} \
                  QTabWidget::tab-bar {border: none;} \
                  QTabBar::tab {border: none;min-height: 28px;min-width: 85px;} \
                  QTabBar::tab:hover,QTabBar::tab:selected {color: rgb(88, 187, 228);} \
                  QTabBar::tab:!enabled {background-color: rgb(180, 180, 180);}");

    tabBar()->installEventFilter(this);
    animation = nullptr;
    m_animationX = -1;
}

QSimpleSliderNavigation::~QSimpleSliderNavigation()
{
    if (animation)
    {
        delete animation;
        animation = nullptr;
    }
}

bool QSimpleSliderNavigation::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == tabBar() && event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent *pMouseEvent = (QMouseEvent *)event;
        if (pMouseEvent->button() == Qt::LeftButton)
        {
            const QPoint pos = pMouseEvent->pos();
            int index = tabBar()->tabAt(pos);
            if (index >= 0)
            {
                int curIndex = tabBar()->currentIndex();
                if (index != curIndex)
                {
                    startAnimation(tabBar()->tabRect(curIndex).x(), tabBar()->tabRect(index).x(), 250);
                }
            }
        }
    }

    return false;
}

void QSimpleSliderNavigation::startAnimation(int beginX,int endX,int duration)
{
    if (!animation)
        animation = new TabBarAnimation(this);
    animation->setStartValue(beginX);
    animation->setEndValue(endX);
    animation->setDuration(duration);
    animation->start();
}

void QSimpleSliderNavigation::setAnimationCurrentValue(int value)
{
    m_animationX = value;
    update();
}

//绘制背景下划线和当前Index的下划线
void QSimpleSliderNavigation::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    int index = tabBar()->currentIndex();
    QRect rect = tabBar()->tabRect(index);
    QStyleOptionTabWidgetFrame option;
    initStyleOption(&option);
    option.lineWidth = 0;
    QStylePainter p(this);
    option.rect = style()->subElementRect(QStyle::SE_TabWidgetTabPane, &option, this);
    p.drawPrimitive(QStyle::PE_FrameTabWidget, option);
    p.fillRect(QRect(option.rect.x(), rect.y() + rect.height(),option.rect.width(),1),QColor(228,231,237));
    int x = (animation && animation->state() == QAbstractAnimation::Running) ? m_animationX : rect.x();
    p.fillRect(QRect(x, rect.y() + rect.height(), rect.width(), 2), QColor(88, 187, 228));
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章