QQ界面模仿1

Posted 一只蚂蚁2

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QQ界面模仿1相关的知识,希望对你有一定的参考价值。

大爱Qt!
QQ中点击联系人或群时,下面的面板是有动态效果的。一时兴起,来实现一下。
[TOC]

效果图

原理

其实实现的方法很多,这里我采用的是QPropertyAnimation。由于想重用代码,所以将动画效果封装在一个QWidget中。
基本思路:带封装的QWidget其实和QStackedWidget或QStackedLayout非常像,唯一不同的地方是在界面切换的时候需要增加动态效果。所以封装的接口也仿照QStackedWidget好了。

代码

class XWidgetAnimation : public QParallelAnimationGroup

    Q_OBJECT

public:
    XWidgetAnimation(QObject* parent = nullptr) 
        :QParallelAnimationGroup(parent)
    
        m_posAnimation = createPropertyAnimation("pos");
        m_posAnimation->setStartValue(QPoint(0, 0));
        m_posAnimation->setEndValue(QPoint(0, 0));

        m_sizeAnimation = createPropertyAnimation("size");
        m_sizeAnimation->setStartValue(QSize(0, 0));
        m_sizeAnimation->setEndValue(QSize(0, 0));
    

    void setTargetObject(QWidget* target)
    
        m_posAnimation->setTargetObject(target);
        m_sizeAnimation->setTargetObject(target);
    
    QWidget* targetObject()const return qobject_cast<QWidget*>( m_posAnimation->targetObject()); 

    void setEndPos(const QPoint& pos) m_posAnimation->setEndValue(pos); 
    QPoint endPos()const return m_posAnimation->endValue().toPoint(); 

    void setEndSize(const QSize& size) m_sizeAnimation->setEndValue(size); 
    QSize endSize()const return m_sizeAnimation->endValue().toSize(); 

    QPoint startPos()const return m_posAnimation->startValue().toPoint(); 
    QSize startSize()const return m_sizeAnimation->startValue().toSize(); 

    void setDuration(int msecs)
    
        m_posAnimation->setDuration(msecs);
        m_sizeAnimation->setDuration(msecs);
    

private:
    QPropertyAnimation* createPropertyAnimation(const QByteArray &propertyName)
    
        QPropertyAnimation* animation = new QPropertyAnimation(this);
        animation->setPropertyName(propertyName);
        addAnimation(animation);

        return animation;
    


    void setStartPos(const QPoint& pos) m_posAnimation->setStartValue(pos); 
    void setStartSize(const QSize& size) m_sizeAnimation->setStartValue(size); 

private:
    QPropertyAnimation* m_posAnimation;
    QPropertyAnimation* m_sizeAnimation;

    friend class XAnimationWidget;
;

class XAnimationWidget : public QWidget

    Q_OBJECT
public:
    XAnimationWidget(QWidget* parent = nullptr)
        :QWidget(parent),m_preWidget(nullptr), m_currentWidget(nullptr)
    
        m_toTargetAnimation = new XWidgetAnimation(this);

        m_fromTargetAnimation = new XWidgetAnimation(this);
        m_fromTargetAnimation->setDirection(QAbstractAnimation::Backward);

        connect(m_toTargetAnimation, SIGNAL(finished()), this, SLOT(onAnimationFinished()));
    

    void addWidget(QWidget* widget)
    
        Q_ASSERT(!m_widgets.contains(widget));

        m_widgets.append(widget);
        widget->setParent(this);
        if (m_currentWidget)
        
            widget->setVisible(false);
        
        else
        
            widget->move(0, 0);
            widget->resize(this->size());
            widget->setVisible(true);
            m_currentWidget = widget;
        
    
    void removeWidget(QWidget* widget)
    
        m_widgets.removeOne(widget);
        if (m_currentWidget == widget)
        
            m_currentWidget = nullptr;
        
    
    void insertWidget(int index, QWidget* widget) m_widgets.insert(index, widget); 

    int count()const return m_widgets.count(); 

    int currentIndex()const return indexOf(m_currentWidget); 
    QWidget* currentWidget()const return m_currentWidget; 

    int indexOf(QWidget* widget)const return m_widgets.indexOf(widget); 
    QWidget* widget(int index)const return m_widgets.at(index); 

    XWidgetAnimation* fromTargetAnimation()const return m_fromTargetAnimation; 
    XWidgetAnimation* toTargetAnimation()const return m_toTargetAnimation; 

    public slots:
    void setCurrentIndex(int index)
    
        setCurrentWidget(widget(index));
    
    void setCurrentWidget(QWidget* widget)
    
        Q_ASSERT(m_widgets.contains(widget));

        if (m_currentWidget == widget)
            return;

        m_preWidget = m_currentWidget;
        m_currentWidget = widget;

        preCurrentWidgetChangedEvent(m_preWidget, m_currentWidget);

        m_toTargetAnimation->stop();
        m_fromTargetAnimation->stop();
        m_toTargetAnimation->setTargetObject(m_preWidget);
        m_fromTargetAnimation->setTargetObject(m_currentWidget);
        if (m_preWidget)
            m_toTargetAnimation->start();
        if (m_currentWidget)
        
            m_fromTargetAnimation->start();
            m_currentWidget->setVisible(true);
            m_currentWidget->raise();
        
    

private slots:
    void onAnimationFinished()
    
        if (m_preWidget)
        
            m_preWidget->setVisible(false);
        
    

protected:
    virtual void resizeEvent(QResizeEvent *event)
    
        m_toTargetAnimation->setStartSize(event->size());
        m_fromTargetAnimation->setStartSize(event->size());
        if (m_currentWidget)
        
            m_currentWidget->resize(event->size());
        
    
    virtual void preCurrentWidgetChangedEvent(QWidget* oldWidget, QWidget* newWidget)

private:
    QList<QWidget*> m_widgets;
    QWidget*        m_preWidget;
    QWidget*        m_currentWidget;

    XWidgetAnimation*   m_toTargetAnimation;
    XWidgetAnimation*   m_fromTargetAnimation;
;


class MainPanelCenterWidget : public XAnimationWidget

    Q_OBJECT
public:
    MainPanelCenterWidget(QWidget* parent = nullptr) 
        :XAnimationWidget(parent)
    
    

protected:
    virtual void resizeEvent(QResizeEvent *event)
    
        XAnimationWidget::resizeEvent(event);
        toTargetAnimation()->setEndSize(event->size());
        fromTargetAnimation()->setEndSize(event->size());
    
    virtual void preCurrentWidgetChangedEvent(QWidget* oldWidget, QWidget* newWidget)
    
        int oldIndex = indexOf(oldWidget);
        int newIndex = indexOf(newWidget);
        int width = this->width();

        if (oldIndex < newIndex)
        
            toTargetAnimation()->setEndPos(QPoint(-width, 0));
            fromTargetAnimation()->setEndPos(QPoint(width, 0));
        
        else
        
            toTargetAnimation()->setEndPos(QPoint(width, 0));
            fromTargetAnimation()->setEndPos(QPoint(-width, 0));
        
    
;

以上是关于QQ界面模仿1的主要内容,如果未能解决你的问题,请参考以下文章

Qt 之 模仿 QQ登陆界面——样式篇

Qt 模仿QQ截图 动态吸附直线

Fdog系列:使用Qt模仿QQ实现登录界面到主界面,功能篇。

Fdog系列:使用Qt模仿QQ实现登录界面到主界面,功能篇。

jsp模仿QQ空间说说的发表

模仿qq空间或朋友圈发布动态评论动态回复评论删除动态或评论的功能(上)