代码简单注释很详细,一开始什么也不能做,只需要创建一个带有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)。