element.ui-Qt實現之Tabs動畫滾動
阿新 • • 發佈:2018-11-07
視覺和互動參考前端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 ¤t) Q_DECL_OVERRIDE; private: QSimpleSliderNavigation* tabs; }; void TabBarAnimation::updateCurrentValue(const QVariant ¤t) { 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)); }