Qt放Element网页滑动菜单栏

基于QTabWidget实现菜单

tabwidget.h

#ifndef TAB_WIDGET_H
#define TAB_WIDGET_H

#include <QTabWidget>
#include <QVariantAnimation>
#include "customcomponent_global.h"

class TabBarAnimation;

class TabWidget : public QTabWidget
{
    Q_OBJECT

public:
    InoTabWidget(QWidget *parent = 0);
    ~InoTabWidget();

    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 *m_animation;
    int m_animationX;
};

#endif

tabwidget.cpp

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

const int AnimateBarWidth = 64;
const int AnimateBarHeight = 2;
const int AnimateBarXOffset = 30;

const int LogoWidth = 140;
const int LogoHeight = 20;

class TabBarAnimation : public QVariantAnimation
{
public:
    TabBarAnimation(InoTabWidget *t) :
        tabs(t)
    {
        setEasingCurve(QEasingCurve::InOutQuad);
    }

    void updateCurrentValue(const QVariant &current) Q_DECL_OVERRIDE;

private:
    InoTabWidget *tabs;
};

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

TabWidget::TabWidget(QWidget *parent) :
    QTabWidget(parent),
    m_animation(nullptr),
    m_animationX(-1)
{
    tabBar()->installEventFilter(this);
    tabBar()->setFixedHeight(40);
}

TabWidget::~TabWidget()
{
    if (m_animation) {
        delete m_animation;
        m_animation = nullptr;
    }
}

bool TabWidget::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) {
                    const QPoint tabBarPos = tabBar()->mapToGlobal(tabBar()->rect().topLeft());
                    startAnimation(tabBarPos.x() + tabBar()->tabRect(curIndex).x() + tabBar()->tabRect(curIndex).width() / 2 - AnimateBarXOffset,
                                   tabBarPos.x() + tabBar()->tabRect(index).x() + tabBar()->tabRect(index).width() / 2 - AnimateBarXOffset, 250);
                }
            }
        }
    }

    return false;
}

void TabWidget::startAnimation(int beginX, int endX, int duration)
{
    if (!m_animation) {
        m_animation = new TabBarAnimation(this);
    }

    m_animation->setStartValue(beginX);
    m_animation->setEndValue(endX);
    m_animation->setDuration(duration);
    m_animation->start();
}

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

// 绘制背景下划线和当前Index的下划线
void TabWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    int index = tabBar()->currentIndex();
    QRect rect = tabBar()->tabRect(index);
    const QPoint tabBarPos = tabBar()->mapToGlobal(tabBar()->rect().topLeft());

    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(), option.rect.width(),
                     rect.y() + rect.height() + AnimateBarHeight * 2),
               QColor(41, 90, 176));
    int x = (m_animation && m_animation->state() == QAbstractAnimation::Running) ?
                m_animationX :
                (tabBarPos.x() + rect.x() + rect.width() / 2 - AnimateBarXOffset);
    p.fillRect(QRect(x, rect.y() + rect.height(),
                     AnimateBarWidth, AnimateBarHeight),
               QColor(255, 255, 255));
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子建莫敌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值