Qt--用QTransform+QPainter+paintEvent+timerEvent实现旋转动画

 代码简单注释很详细,一开始什么也不能做,只需要创建一个带有Widget的项目就可以了

 

接下来看主函数,main.cpp 


#include "widget.h"

#include <QApplication>


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.resize(300,300);
    w.move(100,100);//小控件放在左上角
    w.show();//在show的时候会把paintEvent重写函数执行一遍
    w.startTimer(200);//启动定时器,startTime函数会执行timerEvent函数
    return a.exec();
}

 主要元素是大小移动和外触发超时

然后是 widget.h:

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    Ui::Widget *ui;
    QVector<QPoint> vec_Qpt_six_ori_triangle;//六个方向的三角形
    QVector<QPoint> vec_six_triangle_result;//六个方向的三角形旋转后的结果
    enum class cls_WhereComeFrom{//用来标记从哪里来的绘图,一个是来自构造函数,一个是来自timerEvent
        Construction=0X01,
        TimeoutEvent=0X02
    };
    cls_WhereComeFrom flg_WhereComeFrom;
protected:
    QTransform transform;
    void timerEvent(QTimerEvent *event);
    void paintEvent(QPaintEvent *event);
};
#endif // WIDGET_H

 vec_Qpt_six_ori_triangle 存放六个方向三角形数据用的是vector

vec_six_triangle_result,是上面的经过矩阵变换后的结果,给paintEvent重绘函数再画一遍

 cls_WhereComeFrom枚举是因为函数设计的时候,认为要有一个初使的六个方向三角形,它的旋转在另一个函数中执行,但是paintEvent是没法在构造函数中调用的,所以在构造函数画好那个图形后做一个标记,然后就规定在每个可能发生绘图事件的函数里都加上枚举来标记,在paintEvent中用作判断标记。

void timerEvent(QTimerEvent *event);是父类的虚函数当调用startTimer时且超时调用
void paintEvent(QPaintEvent *event);是父类的重绘虚函数,对象本身show的时候调用一次,之后调用就看对象是不是执行了update了。

 widget.cpp:


#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include <QPainter>
#include <QPoint>
#include <QTransform>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPoint center(150,150);
    QPoint point1(150+16,150-2);
    QPoint point2(150+16,150+2);
    QVector<QPoint> vec_triangle{center,point1,point2};
    vec_Qpt_six_ori_triangle<<vec_triangle;//初始化六方向的三角形
    QTransform transform;
    for(int i=0;i<5;i++){//每旋转1次加入向量vec_Qpt_six_ori_triangle,最后形成六个角的结构
        transform.translate(center.x(), center.y());
        transform.rotate(-60.0);
        transform.translate(-center.x(), -center.y());
        vec_Qpt_six_ori_triangle<<transform.map(vec_triangle);
    }
    flg_WhereComeFrom=cls_WhereComeFrom::Construction;//设置标签
    qDebug()<<vec_Qpt_six_ori_triangle;
}

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

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    if(flg_WhereComeFrom==cls_WhereComeFrom::Construction){//如果来自构造
        painter.setPen(Qt::black);  // 设置画笔颜色为黑色
        QColor myColor(153, 222, 245);
        // 创建一个QBrush对象,并设置为自定义颜色
        QBrush brush(myColor);
        painter.setBrush(brush);
        // 使用drawPolygon函数绘制三角形
        painter.drawPolygon(vec_Qpt_six_ori_triangle);
    }
    if(flg_WhereComeFrom==cls_WhereComeFrom::TimeoutEvent){//如果来自超时事件
        painter.setPen(Qt::black);
        QColor myColor(153, 222, 245);
        QBrush brush(myColor);
        painter.setBrush(brush);
        painter.drawPolygon(vec_six_triangle_result);//旋转后的ploygon
    }
}
void Widget::timerEvent(QTimerEvent *event)
{   transform;
    flg_WhereComeFrom=cls_WhereComeFrom::TimeoutEvent;//设置标签
    transform.translate(150, 150);//每次都旋转-15度
    transform.rotate(-3.0);
    transform.translate(-150, -150);
    vec_six_triangle_result = transform.map(vec_Qpt_six_ori_triangle);
    update();
}

函数作用都已经解释完了。这个旋转有什么用呢?可以检查我们Qt程序是否在顺畅的运行,w对象

启动了startTimer方法,每过200ms,就会在timerEvent指示它自己update更新一下,这时候那个六角结构就会逆时针旋转3°,如果卡住的话它就会有所表现。 

这里实现的比较简单,本来想完成雪花旋转,冰片在末端消逝的样子,但是代码太长了说明不了问题,前提是要理解 QTransform &QTransform::scale(qreal sx, qreal sy)、QTransform &QTransform::rotate(qreal angle, Qt::Axis axis = Qt::ZAxis)、QTransform &QTransform::translate(qreal dx, qreal dy)。

 

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值