带你0到1之QT编程:二十六、实战应用之翻转动画的实现

此为QT编程的第二十六谈!关注我,带你快速学习QT编程的学习路线

每一篇的技术点都是很很重要!很重要!很重要!但不冗余!

我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点!

码农不易,各位学者学到东西请点赞支持支持

开始部分:

总:在开发过程中,难以避免有些高级动画的实现,例如翻转、平移等等。这篇文章将教你们如何实现两个页面如何翻转在同一个对话框。

预设效果如下:

qt的动画旋转demo

分:那么就开始实现这个效果吧!

一、完成页面小模块

1、首先,我需要构建两个页面的模块QWdiget,命名为page1、page2

2、创建完成后,直接去各自的.UI文件添加翻转按钮

3、此时已经完成一半咯!现在完成背景部分,那么就重写QPaintEvent

4、在cpp文件实现即可,此时能看见背景图啦(资源的话自己添加资源文件噢)

5、最重要的是信号触发!当我们点击按钮(转到槽)的时候,触发这个信号,留给存放QWidget的对话框来接收!

此刻的page模块已经完成了,恭喜!page2同理完成即可!

二、利用Qt自带的QStackedWidget来完成动画实现

1、那么这时候我们就要创建一个来实现动画效果的QStackedWidget了,其实也是一个小模块,用来存放page1、page2,并继承了QStackedWidget

2、这时候你需要在.h文件添加QStackWidget头文件

3、我们要如何实现动画呢?本质就是利用绘制事件咯,就如重写背景QPaintEvent,并利用qt自带的QPropertyAnimation动画机制来实现

3.1 先设计好AnimateStackedWidget这个头文件,由于需要使用信号与槽,添加Q_OBJECT宏,和QPROPERTY宏来定义rotateVal旋转角度

3.2 声明paintEvent函数、animation动画启动函数、还有设置旋转起始值、旋转结束值、获取旋转起始值、旋转结束值、获取旋转角度、设置旋转角度

3.3 再自定义成员变量、和自定义槽函数

3.4 此时的头文件基本完成了,这时候就实现函数即可!

3.4.1 先在构造函数设置初始页码、和动画状态

3.4.2 再实现动画启动函数,创建一个QPropertyAnimation对象,来设置起始值、结束值、动画持续性、动画柔和曲线。当旋转角度发生变化的时候,调用对应槽函数;动画完成后,调用对应槽函数

3.4.3 先实现简单的槽函数,本质就是随旋转值的变化,而重复调用绘制事件;还有完成之后,调用基类的QStackedWidget的一些函数,将反面设置到正面

3.4.4 万事俱备,只欠东风!此刻完成绘制事件即可!

// 自定义的绘制事件,负责绘制动画效果
void AnimateStackedWidget::paintEvent(QPaintEvent *event)
{
    QPainter p(this);  // 创建一个 QPainter 对象 p,用于在当前控件上绘制,p 是绘制的工具

    // 判断当前旋转角度是否在 0 到 90 度之间
    if (m_rotateVal > 0 && m_rotateVal <= 90) {
        QPixmap pix(currentWidget()->size());   // 创建一个与当前页面大小相同的 QPixmap 对象(缓存当前页面内容)
        currentWidget()->render(&pix);  // 将当前页面渲染到 QPixmap 中,pix 存储当前页面的图像

        // 创建一个 QTransform 对象,用于旋转和移动图片
        QTransform transform;
        transform.translate(width()/2, 0);  // 平移坐标系原点到控件的中心,旋转会围绕这个点进行
        transform.rotate(m_rotateVal, Qt::YAxis);   // 沿 Y 轴旋转 m_rotateVal 角度,旋转当前页面
        p.setTransform(transform);  // 应用旋转变换,p 设置为旋转后的状态

        // 将旋转后的图像绘制到控件上,图像的左上角位置会根据平移来保证图片居中显示
        p.drawPixmap(-width()/2, 0, pix);  // 将图像绘制到左上角,偏移量为 -width()/2 保证旋转中心对准控件中心
    } else if (m_rotateVal > 90 && m_rotateVal <= 180) {
        // 如果旋转角度在 90° 到 180° 之间,处理翻转到背面的效果
        QPixmap pix(widget(m_pageindex)->size());  // 创建一个与目标页面大小相同的 QPixmap 对象
        widget(m_pageindex)->render(&pix);  // 渲染目标页面的内容到 pix 中

        // 创建旋转变换
        QTransform transform;
        transform.translate(width()/2, 0);  // 将坐标系原点平移到控件的中心,旋转会围绕这个点
        transform.rotate(m_rotateVal + 180, Qt::YAxis);  // 旋转角度增加 180°,达到从正面翻转到背面的效果
        p.setTransform(transform);  // 应用旋转变换

        // 绘制旋转后的图像
        p.drawPixmap(-width()/2, 0, pix);  // 在指定位置绘制图像,确保图像居中显示
    }
    else if (m_rotateVal > -180 && m_rotateVal <= -90) { // 反向旋转,旋转角度从 -180° 到 -90° 之间
        QPixmap pix(widget(m_pageindex)->size());  // 获取目标页面的 QPixmap 缓存
        widget(m_pageindex)->render(&pix);  // 渲染目标页面内容到 pix 中

        // 创建旋转变换
        QTransform transform;
        transform.translate(width()/2, 0);  // 平移坐标系原点到控件的中心
        transform.rotate(m_rotateVal + 180, Qt::YAxis);  // 旋转角度加 180°,模拟从背面翻转回正面
        p.setTransform(transform);  // 应用旋转变换

        // 绘制旋转后的图像
        p.drawPixmap(-width()/2, 0, pix);  // 在指定位置绘制图像
    } else if (m_rotateVal > -90 && m_rotateVal < 0) {
        // 处理从负角度 -90° 到 0° 之间的旋转
        QPixmap pix(currentWidget()->size());  // 获取当前页面的 QPixmap 缓存
        currentWidget()->render(&pix);  // 渲染当前页面内容到 pix 中

        // 创建旋转变换
        QTransform transform;
        transform.translate(width()/2, 0);  // 平移坐标系原点到控件的中心
        transform.rotate(m_rotateVal, Qt::YAxis);  // 沿 Y 轴旋转 m_rotateVal 角度
        p.setTransform(transform);  // 应用旋转变换

        // 绘制旋转后的图像
        p.drawPixmap(-width()/2, 0, pix);  // 在指定位置绘制图像,确保图像居中显示
    }
}

分为两个部分:一个是正向旋转,一个是反向旋转

4.完成以上模块,就可以在对话框中调用这个自定义控件

4.1 先创建一个对话框的类

4.2 完成后,在.h文件导入刚刚实现的三个类,page1、page2、animateStackedWidget的头文件,声明三个类成员,声明接收到page1、page2发出的信号后对应的槽函数

4.3 最后一步!完成.cpp文件,在构造函数设置一些UI属性、将page1、page2添加到animateStackedWidget中,再将animateStackedWidget添加到水平布局管理中、还记得page中emit发出的信号吗?就在这里连接槽函数

4.4 简单实现槽函数,完成!

总:在这次开发中,主要运用了QT中的QPropertyAnimation动画系统、Q_PROPERTY属性系统(需要动态访问和修改对象的成员变量)、还有重绘事件来进行动画的实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值