Qt动画功能学习
1. 项目概述
本项目展示了如何使用Qt的动画框架实现界面元素的动画效果,包括几何属性动画、颜色动画和不透明度动画。Qt提供了强大的动画系统,可以轻松实现各种UI元素的平滑过渡效果,提升用户体验。
1.1 项目结构
48/
├── 48.pro # 项目配置文件
├── main.cpp # 主函数入口
├── widget.h # Widget类头文件
├── widget.cpp # Widget类实现文件
└── widget.ui # 界面设计文件
1.2 功能特点
- 几何属性动画:控制控件的位置和大小变化
- 颜色动画:控制控件的颜色渐变效果
- 不透明度动画:控制控件的透明度变化
- 支持设置动画时长、循环次数和缓和曲线
2. 代码实现
2.1 项目配置文件 (48.pro)
qmake
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
关键点说明:
- 动画功能是Qt核心模块的一部分,不需要额外添加模块
2.2 主函数 (main.cpp)
cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
2.3 Widget类头文件 (widget.h)
cpp
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPropertyAnimation> // 属性动画类
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
// 按钮点击事件处理函数
void on_pushButton_clicked(); // 几何动画按钮
void on_pushButton_2_clicked(); // 颜色动画按钮
void on_pushButton_3_clicked(); // 不透明度动画按钮
private:
Ui::Widget *ui;
// 三种不同类型的属性动画对象
QPropertyAnimation *propertyAnimation; // 几何属性动画
QPropertyAnimation *propertyAnimation1; // 颜色动画
QPropertyAnimation *propertyAnimation2; // 不透明度动画
};
#endif // WIDGET_H
关键点说明:
#include <QPropertyAnimation>
- 包含属性动画相关的头文件- 定义了三个
QPropertyAnimation
指针,分别用于不同类型的动画 - 定义了三个槽函数,用于响应按钮点击事件
2.4 Widget类实现文件 (widget.cpp)
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QGraphicsColorizeEffect> // 颜色效果
#include <QGraphicsOpacityEffect> // 不透明度效果
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 1. 几何属性动画初始化
propertyAnimation = new QPropertyAnimation(ui->geometryWidget, "geometry");
// 设置动画起始值
propertyAnimation->setStartValue(QRect(0, 0, 100, 100));
// 设置某个时间段值(关键帧)
propertyAnimation->setKeyValueAt(0.2, QRect(600, 0, 100, 100));
// 设置结束值
propertyAnimation->setEndValue(QRect(600, 400, 200, 200));
// 设置动画时长(毫秒)
propertyAnimation->setDuration(2000);
// 设置动画循环周期(1表示播放一次,-1表示无限循环)
propertyAnimation->setLoopCount(1);
// 设置动画的缓和曲线(动画曲线)
propertyAnimation->setEasingCurve(QEasingCurve::OutQuart);
// 2. 颜色动画
// 创建颜色效果对象
QGraphicsColorizeEffect *graphicsColorizeEffect = new QGraphicsColorizeEffect(this);
// 将效果应用到控件
ui->colorWidget->setGraphicsEffect(graphicsColorizeEffect);
// 创建属性动画,操作颜色效果的color属性
propertyAnimation1 = new QPropertyAnimation(graphicsColorizeEffect, "color");
// 设置起始颜色
propertyAnimation1->setStartValue(QColor(Qt::yellow)); // 也可以使用 rgb(100, 100, 100)
// 设置结束颜色
propertyAnimation1->setEndValue(QColor(Qt::darkGray)); // 也可以使用 rgb(20, 20, 50)
// 设置动画时长
propertyAnimation1->setDuration(2000);
// 3. 不透明度动画
// 创建不透明度效果对象
QGraphicsOpacityEffect *graphicsOpacityEffect = new QGraphicsOpacityEffect(this);
// 将效果应用到控件
ui->opacityWidget->setGraphicsEffect(graphicsOpacityEffect);
// 创建属性动画,操作不透明度效果的opacity属性
propertyAnimation2 = new QPropertyAnimation(graphicsOpacityEffect, "opacity");
// 设置起始不透明度(0.0表示完全透明)
propertyAnimation2->setStartValue(0.0);
// 设置结束不透明度(1.0表示完全不透明)
propertyAnimation2->setEndValue(1.0);
// 设置动画时长
propertyAnimation2->setDuration(5000);
}
Widget::~Widget()
{
delete ui;
}
// 几何动画按钮点击事件
void Widget::on_pushButton_clicked()
{
// 启动几何动画
propertyAnimation->start();
}
// 颜色动画按钮点击事件
void Widget::on_pushButton_2_clicked()
{
// 启动颜色动画
propertyAnimation1->start();
}
// 不透明度动画按钮点击事件
void Widget::on_pushButton_3_clicked()
{
// 启动不透明度动画
propertyAnimation2->start();
}
关键点说明:
-
几何属性动画:
- 通过
QPropertyAnimation
控制控件的geometry
属性 setStartValue
设置起始几何属性setKeyValueAt
设置中间关键帧(0.2表示动画进行到20%的位置)setEndValue
设置结束几何属性setDuration
设置动画持续时间(毫秒)setLoopCount
设置循环次数setEasingCurve
设置缓和曲线,控制动画的速度变化
- 通过
-
颜色动画:
- 使用
QGraphicsColorizeEffect
创建颜色效果 - 将效果应用到控件
setGraphicsEffect
- 创建属性动画控制效果的
color
属性 - 设置起始颜色和结束颜色
- 使用
-
不透明度动画:
- 使用
QGraphicsOpacityEffect
创建不透明度效果 - 将效果应用到控件
- 创建属性动画控制效果的
opacity
属性 - 设置起始不透明度(0.0)和结束不透明度(1.0)
- 使用
-
动画启动:
- 通过
start()
方法启动动画
- 通过
2.5 界面设计文件 (widget.ui)
xml
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="QWidget" name="geometryWidget" native="true">
<property name="geometry">
<rect>
<x>180</x>
<y>70</y>
<width>120</width>
<height>80</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">QWidget { background-color: rgb(239, 41, 41); }
</string>
</property>
</widget>
<widget class="QWidget" name="colorWidget" native="true">
<property name="geometry">
<rect>
<x>180</x>
<y>170</y>
<width>120</width>
<height>80</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">QWidget { background-color: blue }
</string>
</property>
</widget>
<widget class="QWidget" name="opacityWidget" native="true">
<property name="geometry">
<rect>
<x>180</x>
<y>280</y>
<width>120</width>
<height>80</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">QWidget { background-color: yellow }
</string>
</property>
</widget>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>660</x>
<y>100</y>
<width>115</width>
<height>301</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>几何动画</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>颜色动画</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>不透明度动画</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
关键点说明:
- 界面包含三个自定义控件(QWidget)用于显示动画效果:
geometryWidget
:用于几何动画,背景色为红色colorWidget
:用于颜色动画,背景色为蓝色opacityWidget
:用于不透明度动画,背景色为黄色
- 右侧有三个按钮,用于触发不同类型的动画
3. Qt动画框架详解
3.1 动画类型
类名 | 描述 | 用途 |
---|---|---|
QPropertyAnimation | 属性动画 | 动画化Qt对象的属性变化 |
QVariantAnimation | 变体动画 | QPropertyAnimation的基类,提供变体值之间的插值 |
QPauseAnimation | 暂停动画 | 提供暂停功能 |
QSequentialAnimationGroup | 顺序动画组 | 按顺序播放一组动画 |
QParallelAnimationGroup | 并行动画组 | 同时播放一组动画 |
QAnimationGroup | 动画组 | 所有动画组的基类 |
3.2 图形效果类型
类名 | 描述 | 用途 |
---|---|---|
QGraphicsEffect | 图形效果基类 | 所有图形效果的基类 |
QGraphicsBlurEffect | 模糊效果 | 为控件添加模糊效果 |
QGraphicsColorizeEffect | 颜色效果 | 为控件添加颜色效果 |
QGraphicsDropShadowEffect | 阴影效果 | 为控件添加阴影效果 |
QGraphicsOpacityEffect | 不透明度效果 | 控制控件的不透明度 |
3.3 缓和曲线类型
Qt提供了多种缓和曲线(QEasingCurve),用于控制动画的速度变化:
曲线类型 | 描述 |
---|---|
Linear | 线性变化,匀速动画 |
InQuad, OutQuad, InOutQuad | 二次方缓动 |
InCubic, OutCubic, InOutCubic | 三次方缓动 |
InQuart, OutQuart, InOutQuart | 四次方缓动 |
InQuint, OutQuint, InOutQuint | 五次方缓动 |
InSine, OutSine, InOutSine | 正弦缓动 |
InExpo, OutExpo, InOutExpo | 指数缓动 |
InCirc, OutCirc, InOutCirc | 圆形缓动 |
InElastic, OutElastic, InOutElastic | 弹性缓动 |
InBack, OutBack, InOutBack | 回弹缓动 |
InBounce, OutBounce, InOutBounce | 弹跳缓动 |
4. 实现步骤详解
4.1 创建属性动画
cpp
// 创建属性动画对象
QPropertyAnimation *animation = new QPropertyAnimation(targetObject, "propertyName");
// 设置动画参数
animation->setStartValue(startValue); // 起始值
animation->setEndValue(endValue); // 结束值
animation->setDuration(duration); // 持续时间(毫秒)
animation->setLoopCount(loopCount); // 循环次数
animation->setEasingCurve(easingCurve); // 缓和曲线
// 启动动画
animation->start();
4.2 创建关键帧动画
cpp
// 创建属性动画对象
QPropertyAnimation *animation = new QPropertyAnimation(targetObject, "propertyName");
// 设置动画参数
animation->setStartValue(startValue); // 起始值
animation->setKeyValueAt(0.25, value1); // 25%位置的值
animation->setKeyValueAt(0.5, value2); // 50%位置的值
animation->setKeyValueAt(0.75, value3); // 75%位置的值
animation->setEndValue(endValue); // 结束值
animation->setDuration(duration); // 持续时间(毫秒)
// 启动动画
animation->start();
4.3 创建图形效果
cpp
// 创建图形效果
QGraphicsEffect *effect = new QGraphicsXXXEffect(parent);
// 配置效果参数
// ...
// 应用效果到控件
widget->setGraphicsEffect(effect);
// 创建动画控制效果属性
QPropertyAnimation *animation = new QPropertyAnimation(effect, "propertyName");
// ...
4.4 创建动画组
cpp
// 创建顺序动画组
QSequentialAnimationGroup *sequentialGroup = new QSequentialAnimationGroup();
// 添加子动画
sequentialGroup->addAnimation(animation1);
sequentialGroup->addAnimation(animation2);
sequentialGroup->addAnimation(animation3);
// 启动动画组
sequentialGroup->start();
// 创建并行动画组
QParallelAnimationGroup *parallelGroup = new QParallelAnimationGroup();
// 添加子动画
parallelGroup->addAnimation(animation1);
parallelGroup->addAnimation(animation2);
parallelGroup->addAnimation(animation3);
// 启动动画组
parallelGroup->start();
5. 常用功能示例
5.1 控制动画状态
cpp
// 启动动画
animation->start();
// 暂停动画
animation->pause();
// 恢复动画
animation->resume();
// 停止动画
animation->stop();
// 设置当前时间
animation->setCurrentTime(msecs);
5.2 动画事件处理
cpp
// 连接动画信号
connect(animation, &QPropertyAnimation::finished, this, &MyClass::onAnimationFinished);
connect(animation, &QPropertyAnimation::stateChanged, this, &MyClass::onStateChanged);
connect(animation, &QPropertyAnimation::currentLoopChanged, this, &MyClass::onLoopChanged);
// 事件处理函数
void MyClass::onAnimationFinished()
{
qDebug() << "Animation finished";
// 处理动画完成事件
}
void MyClass::onStateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
{
qDebug() << "State changed from" << oldState << "to" << newState;
// 处理状态变化事件
}
void MyClass::onLoopChanged(int currentLoop)
{
qDebug() << "Current loop:" << currentLoop;
// 处理循环变化事件
}
5.3 自定义动画属性
对于没有内置动画属性的对象,可以使用Q_PROPERTY宏定义自定义属性:
cpp
class MyObject : public QObject
{
Q_OBJECT
Q_PROPERTY(float customValue READ customValue WRITE setCustomValue)
public:
MyObject(QObject *parent = nullptr) : QObject(parent), m_customValue(0.0) {}
float customValue() const { return m_customValue; }
void setCustomValue(float value) {
if (m_customValue != value) {
m_customValue = value;
update(); // 触发更新
}
}
private:
float m_customValue;
};
// 使用自定义属性创建动画
MyObject *obj = new MyObject(this);
QPropertyAnimation *animation = new QPropertyAnimation(obj, "customValue");
animation->setStartValue(0.0);
animation->setEndValue(1.0);
animation->setDuration(1000);
animation->start();
7.1 状态机动画
Qt提供了状态机框架,可以与动画系统结合使用:
cpp
#include <QStateMachine>
#include <QState>
#include <QPropertyAnimation>
// 创建状态机
QStateMachine *machine = new QStateMachine(this);
// 创建状态
QState *state1 = new QState(machine);
QState *state2 = new QState(machine);
// 设置状态的属性值
state1->assignProperty(widget, "geometry", QRect(0, 0, 100, 100));
state2->assignProperty(widget, "geometry", QRect(200, 200, 200, 200));
// 添加状态转换
state1->addTransition(button, &QPushButton::clicked, state2);
state2->addTransition(button, &QPushButton::clicked, state1);
// 设置动画
QPropertyAnimation *animation = new QPropertyAnimation(widget, "geometry");
animation->setDuration(1000);
// 将动画添加到状态机
machine->addDefaultAnimation(animation);
// 设置初始状态并启动状态机
machine->setInitialState(state1);
machine->start();
7.2 动画与样式表结合
cpp
// 创建动画控制样式表属性
QPropertyAnimation *animation = new QPropertyAnimation(widget, "styleSheet");
// 设置样式表变化
animation->setStartValue("background-color: red;");
animation->setEndValue("background-color: blue;");
animation->setDuration(1000);
// 启动动画
animation->start();
7.3 动画与图形视图框架结合
cpp
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QPropertyAnimation>
// 创建场景和视图
QGraphicsScene *scene = new QGraphicsScene(this);
QGraphicsView *view = new QGraphicsView(scene, this);
// 创建图形项
QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
rect->setBrush(QBrush(Qt::red));
scene->addItem(rect);
// 创建动画
QPropertyAnimation *animation = new QPropertyAnimation(rect, "pos");
animation->setStartValue(QPointF(0, 0));
animation->setEndValue(QPointF(200, 200));
animation->setDuration(2000);
animation->setLoopCount(-1); // 无限循环
// 启动动画
animation->start();