Qt中使用动画组管理动画的状态

16 篇文章 1 订阅
16 篇文章 1 订阅

先上效果:

 工程下载地址:

https://download.csdn.net/download/shuishou1000/24589450

1,创建mainwindow工程,添加三个按钮(pushbutton)。

2,下一步,在mainWindow的构造函数中为每一个按钮添加动画。

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //添加动画
    QPropertyAnimation *animation1=new QPropertyAnimation(ui->pushButton,"geometry");
    animation1->setDuration(3000);
    animation1->setStartValue(ui->pushButton->geometry());
    animation1->setEndValue(QRect(50,200,100,50));
    
    QPropertyAnimation *animation2=new QPropertyAnimation(ui->pushButton_2,"geometry");
    animation1->setDuration(3000);
    animation1->setStartValue(ui->pushButton_2->geometry());
    animation1->setEndValue(QRect(150,200,100,50));
    
    QPropertyAnimation *animation3=new QPropertyAnimation(ui->pushButton_3,"geometry");
    animation1->setDuration(3000);
    animation1->setStartValue(ui->pushButton_3->geometry());
    animation1->setEndValue(QRect(250,200,100,50));
}

MainWindow::~MainWindow()
{
    delete ui;
}

3,继续添加曲线,为这三个按钮添加同样的曲线。

QEasingCurve curve;
curve.setType(QEasingCurve::OutBounce);
curve.setAmplitude(1.00);
curve.setOvershoot(1.70);
curve.setPeriod(0.30);

animation1->setEasingCurve(curve);
animation2->setEasingCurve(curve);
animation3->setEasingCurve(curve);

4,一旦三个动画都添加了缓动曲线,我们就可以将所有三个动画添加到一个动画组里

//QParallelAnimationGroup *group=new QParallelAnimationGroup;
QSequentialAnimationGroup *group=new QSequentialAnimationGroup;
group->addAnimation(animation1);
group->addAnimation(animation2);
group->addAnimation(animation3);

5,调用start(),启动刚刚创建的动画组。

group->start();

我们使用动画组启动动画。

动画顺序设置QParallelAnimationGroup是同时播放,QSequentialAnimationGroup是按添加动画的顺序播放

 //QParallelAnimationGroup *group=new QParallelAnimationGroup;
    QSequentialAnimationGroup *group=new QSequentialAnimationGroup;

因为QParallelAnimationGroup和QSequentialAnimationGroup都是继承子QAbstractAnimator类,所以,他们之间可以进行相互添加使用addAnimation.

QParallelAnimationGroup同时播放所有动画,以最长的动画为准。

QSequentialAnimationGroup 按照添加动画的顺序播放动画。只有当一个动画完成了,再播放另外的动画。

这两个组是目前QT提供的,他们控制动画的开始,暂停,结束,顺序。

动画嵌套组的通常使用方法是:将QParallelAnimationGroup放入到QSequentialAnimationGroup中,顺序播放一组一组的动画。 

举例说明

1,使用之前的例子多放入一些按钮。

2,为所有按钮添加动画和缓动曲线

    //添加动画
    QPropertyAnimation *animation1=new QPropertyAnimation(ui->pushButton,"geometry");
    animation1->setDuration(3000);
    animation1->setStartValue(ui->pushButton->geometry());
    animation1->setEndValue(QRect(50,50,100,50));

    QPropertyAnimation *animation2=new QPropertyAnimation(ui->pushButton_2,"geometry");
    animation2->setDuration(3000);
    animation2->setStartValue(ui->pushButton_2->geometry());
    animation2->setEndValue(QRect(150,50,100,50));

    QPropertyAnimation *animation3=new QPropertyAnimation(ui->pushButton_3,"geometry");
    animation3->setDuration(3000);
    animation3->setStartValue(ui->pushButton_3->geometry());
    animation3->setEndValue(QRect(250,50,100,50));

    QPropertyAnimation *animation4=new QPropertyAnimation(ui->pushButton_4,"geometry");
    animation4->setStartValue(ui->pushButton_4->geometry());
    animation4->setDuration(3000);
    animation4->setEndValue(QRect(50,200,100,50));

    QPropertyAnimation *animation5=new QPropertyAnimation(ui->pushButton_5,"geometry");
    animation5->setStartValue(ui->pushButton_5->geometry());
    animation5->setDuration(3000);
    animation5->setEndValue(QRect(150,200,100,50));

    QPropertyAnimation *animation6=new QPropertyAnimation(ui->pushButton_6,"geometry");
    animation6->setStartValue(ui->pushButton_6->geometry());
    animation6->setDuration(3000);
    animation6->setEndValue(QRect(200,200,100,50));


    //创建曲线控制器
    QEasingCurve curve;
    curve.setType(QEasingCurve::OutBounce);
    curve.setAmplitude(1.00);
    curve.setOvershoot(1.70);
    curve.setPeriod(0.30);

    animation1->setEasingCurve(curve);
    animation2->setEasingCurve(curve);
    animation3->setEasingCurve(curve);
    animation4->setEasingCurve(curve);
    animation5->setEasingCurve(curve);
    animation6->setEasingCurve(curve);

 3,添加动画组

//创建 动画组
    QParallelAnimationGroup *group=new QParallelAnimationGroup;
    QParallelAnimationGroup *group2=new QParallelAnimationGroup;

    QSequentialAnimationGroup *groupAll=new QSequentialAnimationGroup;
    group->addAnimation(animation1);
    group->addAnimation(animation2);
    group->addAnimation(animation3);

    group2->addAnimation(animation4);
    group2->addAnimation(animation5);
    group2->addAnimation(animation6);

4,嵌套动画组并播放

    groupAll->addAnimation(group);
    groupAll->addAnimation(group2);

    //启动动画
    groupAll->start();

效果:先播放上排按钮,再播放下排按钮。

待放动图。

通过动画组的代码设定可以完成复杂的GUI动画。更少的代码,更好的效果。

附录完整代码mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //添加动画
    QPropertyAnimation *animation1=new QPropertyAnimation(ui->pushButton,"geometry");
    animation1->setDuration(3000);
    animation1->setStartValue(ui->pushButton->geometry());
    animation1->setEndValue(QRect(50,50,100,50));

    QPropertyAnimation *animation2=new QPropertyAnimation(ui->pushButton_2,"geometry");
    animation2->setDuration(3000);
    animation2->setStartValue(ui->pushButton_2->geometry());
    animation2->setEndValue(QRect(150,50,100,50));

    QPropertyAnimation *animation3=new QPropertyAnimation(ui->pushButton_3,"geometry");
    animation3->setDuration(3000);
    animation3->setStartValue(ui->pushButton_3->geometry());
    animation3->setEndValue(QRect(250,50,100,50));

    QPropertyAnimation *animation4=new QPropertyAnimation(ui->pushButton_4,"geometry");
    animation4->setStartValue(ui->pushButton_4->geometry());
    animation4->setDuration(3000);
    animation4->setEndValue(QRect(50,200,100,50));

    QPropertyAnimation *animation5=new QPropertyAnimation(ui->pushButton_5,"geometry");
    animation5->setStartValue(ui->pushButton_5->geometry());
    animation5->setDuration(3000);
    animation5->setEndValue(QRect(150,200,100,50));

    QPropertyAnimation *animation6=new QPropertyAnimation(ui->pushButton_6,"geometry");
    animation6->setStartValue(ui->pushButton_6->geometry());
    animation6->setDuration(3000);
    animation6->setEndValue(QRect(250,200,100,50));


    //创建曲线控制器
    QEasingCurve curve;
    curve.setType(QEasingCurve::OutBounce);
    curve.setAmplitude(1.00);
    curve.setOvershoot(1.70);
    curve.setPeriod(0.30);

    animation1->setEasingCurve(curve);
    animation2->setEasingCurve(curve);
    animation3->setEasingCurve(curve);
    animation4->setEasingCurve(curve);
    animation5->setEasingCurve(curve);
    animation6->setEasingCurve(curve);

    //创建 动画组
    QParallelAnimationGroup *group=new QParallelAnimationGroup;
    QParallelAnimationGroup *group2=new QParallelAnimationGroup;

    QSequentialAnimationGroup *groupAll=new QSequentialAnimationGroup;
    group->addAnimation(animation1);
    group->addAnimation(animation2);
    group->addAnimation(animation3);

    group2->addAnimation(animation4);
    group2->addAnimation(animation5);
    group2->addAnimation(animation6);

    groupAll->addAnimation(group);
    groupAll->addAnimation(group2);

    //启动动画
    groupAll->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

欢迎关注公众号 “QML教程”,获取新的内容


​​​​​​​

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Qt、OpenGL和Assimp实现骨骼动画的示例代码: 首先,需要在项目包含assimp库和Qt的OpenGL模块。可以使用以下命令将它们添加到.pro文件: ``` LIBS += -lassimp QT += opengl ``` 然后,需要编写一个用于渲染模型的OpenGL窗口类。以下是一个简单的示例: ```cpp #include <QOpenGLWidget> #include <QOpenGLFunctions> #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h> class OpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions { public: OpenGLWidget(QWidget *parent = 0); ~OpenGLWidget(); protected: void initializeGL(); void resizeGL(int w, int h); void paintGL(); private: Assimp::Importer m_importer; const aiScene *m_scene; }; ``` 在初始化函数,需要加载模型并设置OpenGL状态: ```cpp void OpenGLWidget::initializeGL() { initializeOpenGLFunctions(); // Load model m_scene = m_importer.ReadFile("model.dae", aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_LimitBoneWeights); // Set up OpenGL state glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } ``` 在绘制函数,需要遍历场景的所有节点和网格,并计算每个节点的变换矩阵。以下是绘制函数的示例代码: ```cpp void OpenGLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set up camera glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (double)width() / (double)height(), 0.1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // Draw meshes for (unsigned int i = 0; i < m_scene->mNumMeshes; i++) { const aiMesh *mesh = m_scene->mMeshes[i]; // Set up vertex positions and normals glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, mesh->mVertices); glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, mesh->mNormals); // Set up bone weights and indices if (mesh->HasBones()) { glEnableVertexAttribArray(4); glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(VertexBoneData), (const GLvoid*)offsetof(VertexBoneData, weights)); glEnableVertexAttribArray(5); glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(VertexBoneData), (const GLvoid*)offsetof(VertexBoneData, indices)); // Calculate bone matrices std::vector<aiMatrix4x4> boneMatrices(mesh->mNumBones); for (unsigned int j = 0; j < mesh->mNumBones; j++) { const aiBone *bone = mesh->mBones[j]; aiMatrix4x4 boneMatrix = bone->mOffsetMatrix; const aiNode *node = m_scene->mRootNode->FindNode(bone->mName); while (node && node != mesh->mBones[j]->mNode) { boneMatrix = node->mTransformation * boneMatrix; node = node->mParent; } boneMatrices[j] = boneMatrix; } // Set up bone matrices glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram.programId(), "boneMatrices"), mesh->mNumBones, GL_FALSE, (const GLfloat*)&boneMatrices[0]); } // Draw triangles glDrawElements(GL_TRIANGLES, mesh->mNumFaces * 3, GL_UNSIGNED_INT, mesh->mFaces[0].mIndices); // Disable vertex and normal arrays glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); // Disable bone weights and indices if (mesh->HasBones()) { glDisableVertexAttribArray(4); glDisableVertexAttribArray(5); } } // Swap buffers swapBuffers(); } ``` 在这个示例,假设模型使用了骨骼动画。因此,需要设置每个网格的顶点数据结构,其包含每个顶点的骨骼权重和索引。以下是这个数据结构的示例代码: ```cpp struct VertexBoneData { float weights[4]; unsigned int indices[4]; }; ``` 在顶点着色器,需要将顶点位置和法线变换为相机空间,并使用骨骼权重和索引来计算每个顶点的最终位置。以下是顶点着色器的示例代码: ```glsl #version 330 uniform mat4 projectionMatrix; uniform mat4 modelViewMatrix; uniform mat4 boneMatrices[100]; in vec3 vertexPosition; in vec3 vertexNormal; in vec4 vertexWeights; in ivec4 vertexIndices; out vec3 normal; void main() { mat4 boneMatrix = boneMatrices[vertexIndices.x] * vertexWeights.x; boneMatrix += boneMatrices[vertexIndices.y] * vertexWeights.y; boneMatrix += boneMatrices[vertexIndices.z] * vertexWeights.z; boneMatrix += boneMatrices[vertexIndices.w] * vertexWeights.w; gl_Position = projectionMatrix * modelViewMatrix * boneMatrix * vec4(vertexPosition, 1.0); normal = normalize(mat3(modelViewMatrix * boneMatrix) * vertexNormal); } ``` 在片段着色器,可以使用法线和光照计算每个像素的颜色。以下是片段着色器的示例代码: ```glsl #version 330 uniform vec3 lightPosition; in vec3 normal; out vec4 fragmentColor; void main() { vec3 ambientColor = vec3(0.2, 0.2, 0.2); vec3 diffuseColor = vec3(1.0, 1.0, 1.0); vec3 specularColor = vec3(1.0, 1.0, 1.0); float shininess = 50.0; vec3 lightDirection = normalize(lightPosition - gl_FragCoord.xyz); vec3 normalDirection = normalize(normal); vec3 reflectionDirection = reflect(-lightDirection, normalDirection); float diffuseFactor = max(dot(lightDirection, normalDirection), 0.0); vec3 diffuseComponent = diffuseColor * diffuseFactor; float specularFactor = pow(max(dot(reflectionDirection, normalize(-gl_FragCoord.xyz)), 0.0), shininess); vec3 specularComponent = specularColor * specularFactor; fragmentColor = vec4(ambientColor + diffuseComponent + specularComponent, 1.0); } ``` 最后,需要在Qt应用程序创建OpenGL窗口并运行事件循环。以下是一个简单的示例: ```cpp #include <QApplication> #include "OpenGLWidget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); OpenGLWidget w; w.show(); return a.exec(); } ``` 这就是使用Qt、OpenGL和Assimp实现骨骼动画的基本步骤和代码示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值