一、效果

Qt_Animation.gif

二、代码

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPushButton>
#include <QPropertyAnimation>
#include <QDebug>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);

protected:
    void showEvent(QShowEvent *event);

private:
    QPushButton *m_pBtnRed;
    QPushButton *m_pBtnBlue;
    QPushButton *m_pBtnYellow;

    QWidget *m_pWidgetRed;
    QWidget *m_pWidgetBlue;
    QWidget *m_pWidgetYellow;
};
#endif // WIDGET_H

Widget.cpp

#include "Widget.h"

// 透明度改变动画(windowOpacity属性只能对顶级窗口使用,例如Qt::Tool窗口,对普通控件这些无效)
template<typename func>
static inline void animationOpacity(QWidget *target, const QVariant &startValue, const QVariant &endValue, int duration, func onFinished = nullptr)
{
    QPropertyAnimation *pAnimation = new QPropertyAnimation(target, "windowOpacity", target);
    pAnimation->setStartValue(target->property("windowOpacity"));
    pAnimation->setStartValue(startValue);
    pAnimation->setEndValue(endValue);
    pAnimation->setDuration(duration);
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped); // 动画完成后自动删除
    QObject::connect(pAnimation, &QPropertyAnimation::finished, target, onFinished);
}

// 摇晃动画
template<typename func>
static inline void animationShake(QWidget *target, int duration, int distance, func onFinished = nullptr)
{
    QRect rect = target->rect().adjusted(target->x(), target->y(), 0, 0);

    QPropertyAnimation *pAnimation = new QPropertyAnimation(target, "geometry");
    pAnimation->setDuration(duration);
    pAnimation->setKeyValueAt(0, rect.adjusted(-distance, distance, 0, 0)); // 设置动画结束位置及其大小
    pAnimation->setKeyValueAt(0.1, rect.adjusted(distance, -distance, 0, 0));
    pAnimation->setKeyValueAt(0.2, rect.adjusted(-distance, distance, 0, 0));
    pAnimation->setKeyValueAt(0.3, rect.adjusted(distance, -distance, 0, 0));
    pAnimation->setKeyValueAt(0.4, rect.adjusted(-distance, distance, 0, 0));
    pAnimation->setKeyValueAt(0.5, rect.adjusted(distance, -distance, 0, 0));
    pAnimation->setKeyValueAt(0.6, rect.adjusted(-distance, distance, 0, 0));
    pAnimation->setKeyValueAt(0.7, rect.adjusted(distance, -distance, 0, 0));
    pAnimation->setKeyValueAt(0.8, rect.adjusted(-distance, distance, 0, 0));
    pAnimation->setKeyValueAt(0.9, rect.adjusted(distance, -distance, 0, 0));
    pAnimation->setKeyValueAt(1, rect.adjusted(0, 0, 0, 0));
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);

    QObject::connect(pAnimation, &QPropertyAnimation::finished, target, onFinished);
}

// 移动动画
template<typename func>
static inline void animationMove(QWidget *target, int duration, QPoint point, func onFinished = nullptr)
{
    QPropertyAnimation *pAnimation = new QPropertyAnimation(target, "pos");
    pAnimation->setDuration(duration);
    pAnimation->setStartValue(target->pos());
    pAnimation->setEndValue(target->pos() + point);
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
    QObject::connect(pAnimation, &QPropertyAnimation::finished, target, onFinished);
}

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->setFixedSize(800, 800);

    // 红色动画按钮
    m_pBtnRed = new QPushButton(this);
    m_pBtnRed->setFixedSize(120, 60);
    m_pBtnRed->setText("红色界面动画");
    m_pBtnRed->move(100, 100);
    // 蓝色动画按钮
    m_pBtnBlue = new QPushButton(this);
    m_pBtnBlue->setFixedSize(120, 60);
    m_pBtnBlue->setText("蓝色界面动画");
    m_pBtnBlue->move(300, 100);
    // 黄色动画按钮
    m_pBtnYellow = new QPushButton(this);
    m_pBtnYellow->setFixedSize(120, 60);
    m_pBtnYellow->setText("黄色界面动画");
    m_pBtnYellow->move(500, 100);

    // 红色界面
    m_pWidgetRed = new QWidget(this);
    m_pWidgetRed->setFixedSize(200, 200);
    m_pWidgetRed->move(QPoint(50, 200));
    m_pWidgetRed->setObjectName("Widget1");
    m_pWidgetRed->setStyleSheet("QWidget#Widget1{background: red;}");
    m_pWidgetRed->show();

    // 蓝色界面
    m_pWidgetBlue = new QWidget(this);
    m_pWidgetBlue->setFixedSize(200, 200);
    m_pWidgetBlue->move(300, 200);
    m_pWidgetBlue->setObjectName("Widget2");
    m_pWidgetBlue->setStyleSheet("QWidget#Widget2{background: blue;}");
    m_pWidgetBlue->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    m_pWidgetBlue->show();

    // 黄色界面
    m_pWidgetYellow = new QWidget(this);
    m_pWidgetYellow->setFixedSize(200, 200);
    m_pWidgetYellow->move(550, 200);
    m_pWidgetYellow->setObjectName("Widget3");
    m_pWidgetYellow->setStyleSheet("QWidget#Widget3{background: yellow;}");
    m_pWidgetYellow->show();

    // 红色动画按钮
    connect(m_pBtnRed, &QPushButton::clicked, [=]{
        // 移动动画
        animationMove(m_pWidgetRed, 300, QPoint(0, 200), [=](){
            qDebug() << "移动动画完成";

            animationMove(m_pWidgetRed, 300, QPoint(0, -200), [=](){
                qDebug() << "移动动画返回原处";
            });
        });
    });

    // 蓝色动画按钮
    connect(m_pBtnBlue, &QPushButton::clicked, [=]{
        // 隐藏动画
        animationOpacity(m_pWidgetBlue, 1.0, 0.0, 800, [=]() {
            qDebug() << "隐藏动画完成";

            animationOpacity(m_pWidgetBlue, 0.0, 1.0, 800, [=]{});
        });
    });

    // 黄色动画按钮
    connect(m_pBtnYellow, &QPushButton::clicked, [=]{
        // 摇晃动画
        animationShake(m_pWidgetYellow, 500, 5, [=](){
            qDebug() << "摇晃动画完成";
        });
    });
}

void Widget::showEvent(QShowEvent *event)
{
    Q_UNUSED(event);

    m_pWidgetBlue->move(this->pos().x() + 300, this->pos().y() + 200 + 30);
}