Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How can I optimize a animation I make for QTabWidget



  • Hi
    I have written a class inheritanced QTabWidget with QPropertyAnimation.

    It can work but I think it is so expensive.

    Could you give me some suggestions?

    #ifndef CANIMATIONTABWIDGET_H
    #define CANIMATIONTABWIDGET_H
    
    #include <QPainter>
    #include <QVariant>
    #include <QTabWidget>
    #include <QPropertyAnimation>
    
    class CAnimationTabWidget : public QTabWidget
    {
        Q_OBJECT
    public:
        enum AnimationType
        {
            TopToBottom,
            BottomToTop,
            LeftToRight,
            RightToLeft
        };
    
        explicit CAnimationTabWidget(QWidget *parent = 0);
        virtual ~CAnimationTabWidget();
    
        void start(int index);
        void setLength(int length, AnimationType type);
    
        void setDuration(int duration);
        int getDuration() const;
    
    private slots:
        void valueChanged(const QVariant &value);
        void animationStarted(QAbstractAnimation::State before, QAbstractAnimation::State after);
        void animationFinished();
    
    protected:
        virtual void paintEvent(QPaintEvent *event);
        void renderPreviousWidget(QPainter &painter, QTransform &transform);
        void renderCurrentWidget(QPainter &painter, QTransform &transform);
    
    private:
        bool m_PaintSwitch;
        bool m_isAnimating;
        int m_currentValue;
        int m_currentIndex, m_previousIndex;
        AnimationType m_type;
        QPropertyAnimation *m_animation;
    };
    
    #endif // CANIMATIONTABWIDGET_H
    
    
    
    
    #include "CAnimationTabWidget.h"
    
    #include <QDebug>
    #include <QTabBar>
    
    CAnimationTabWidget::CAnimationTabWidget(QWidget *parent) :
        QTabWidget(parent),
        m_isAnimating(false),
        m_currentValue(0),
        m_currentIndex(0),
        m_previousIndex(0)
    {
        m_animation = new QPropertyAnimation(this, QByteArray());
        m_animation->setDuration(500);
        m_animation->setEasingCurve(QEasingCurve::OutSine);
        m_animation->setStartValue(0);
        m_animation->setEndValue(0);
        connect(m_animation, SIGNAL(valueChanged(QVariant)), SLOT(valueChanged(QVariant)));
        connect(m_animation, SIGNAL(finished()), SLOT(animationFinished()));
    }
    
    CAnimationTabWidget::~CAnimationTabWidget()
    {
        delete m_animation;
    }
    
    void CAnimationTabWidget::start(int index)
    {
        if(m_isAnimating)
        {
            m_animation->stop();
            m_isAnimating = false;
        }
    
        m_previousIndex = m_currentIndex;
        m_currentIndex = index;
        if(m_previousIndex == m_currentIndex)
        {
            qDebug()<<"same index";
            return;
        }
    
        int offsetx = frameSize().width();
        int offsety = frameSize().height();
        widget(m_currentIndex)->setGeometry(0, 0, offsetx, offsety);
    
        currentWidget()->hide();
        m_isAnimating = true;
        m_animation->start();
    }
    
    void CAnimationTabWidget::setLength(int length, CAnimationTabWidget::AnimationType type)
    {
        switch(m_type = type)
        {
            case BottomToTop :
            case LeftToRight :
                    {
                        m_animation->setStartValue(-length/2);
                        m_animation->setEndValue(length/2);
                        break;
                    }
            case TopToBottom :
            case RightToLeft :
                    {
                        m_animation->setStartValue(length/2);
                        m_animation->setEndValue(-length/2);
                        break;
                    }
        }
    }
    
    void CAnimationTabWidget::setDuration(int duration)
    {
        m_animation->setDuration(duration);
    }
    
    int CAnimationTabWidget::getDuration() const
    {
        return m_animation->duration();
    }
    
    void CAnimationTabWidget::valueChanged(const QVariant &value)
    {
        m_currentValue = value.toInt();
        update();
    }
    
    void CAnimationTabWidget::animationStarted(QAbstractAnimation::State before ,QAbstractAnimation::State after)
    {
        qDebug()<<before<<after;
    }
    
    void CAnimationTabWidget::animationFinished()
    {
        m_currentValue = 0;
        m_isAnimating = false;
        QWidget *w = widget(m_currentIndex);
        w->show();
        w->raise();
        setCurrentWidget( w );
        update();
    }
    
    void CAnimationTabWidget::paintEvent(QPaintEvent *event)
    {
        if(m_isAnimating)
        {
    //        raise();
            QPainter painter(this);
            QTransform transform;
            renderCurrentWidget(painter, transform);
            renderPreviousWidget(painter, transform);
    //        lower();
        }
        else
        {
            QWidget::paintEvent(event);
        }
    }
    
    void CAnimationTabWidget::renderPreviousWidget(QPainter &painter, QTransform &transform)
    {
        QWidget *w = widget(m_previousIndex);
        QPixmap pixmap( w->size() );
        w->render(&pixmap,QPoint(),QRegion(),RenderFlags(DrawChildren));
    
        Q_UNUSED(transform);
        switch(m_type)
        {
            case BottomToTop :
                    {
                        painter.drawPixmap(tabBar()->width(), height()/2, pixmap);
                        break;
                    }
            case TopToBottom :
                    {
                        painter.drawPixmap(tabBar()->width(), -height()/2, pixmap);
                        break;
                    }
            case LeftToRight :
                    {
                        painter.drawPixmap(width()/2, 0, pixmap);
                        break;
                    }
            case RightToLeft :
                    {
                        painter.drawPixmap(-width()/2, 0, pixmap);
                        break;
                    }
        }
    }
    
    void CAnimationTabWidget::renderCurrentWidget(QPainter &painter, QTransform &transform)
    {
        QWidget *w = widget(m_currentIndex);
        QPixmap pixmap( w->size() );
        w->render(&pixmap,QPoint(),QRegion(),RenderFlags(DrawChildren));
    
        switch(m_type)
        {
            case BottomToTop :
                    {
                        transform.translate(0, m_currentValue);
                        painter.setTransform(transform);
                        painter.drawPixmap(tabBar()->width(), -height()/2, pixmap);
                        break;
                    }
            case TopToBottom :
                    {
                        transform.translate(0, m_currentValue);
                        painter.setTransform(transform);
                        painter.drawPixmap(tabBar()->width(), height()/2, pixmap);
                        break;
                    }
            case LeftToRight :
                    {
                        transform.translate(m_currentValue, 0);
                        painter.setTransform(transform);
                        painter.drawPixmap(-width()/2, 0, pixmap);
                        break;
                    }
            case RightToLeft :
                    {
                        transform.translate(m_currentValue, 0);
                        painter.setTransform(transform);
                        painter.drawPixmap(width()/2, 0, pixmap);
                        break;
                    }
        }
    }
    
    

    Regards
    Mihan


Log in to reply