Qt5--雷达图
源博客:http://www.fearlazy.com/index.php/post/31.html
工程文件下载
这位大神写的好,便于学习所以将它记录到这里。
使用Qt的Widget来实现一个雷达扫描的图像。
工程架构图:
雷达效果包括三个部分:背景、转动的扇形和闪烁的点。
1.背景的实现很简单,首先填充背景色,然后绘制横纵坐标轴以及三个同心圆。代码如下:
//背景painter.fillRect(rect(),QColor(15,45,188));//边长int len = m_drawArea.width();//底盘(x轴、y轴和3个圆)painter.setPen(QPen(Qt::white));painter.drawLine(m_drawArea.topLeft() + QPoint(0,len/2),m_drawArea.topRight() + QPoint(0,len/2));painter.drawLine(m_drawArea.topLeft() + QPoint(len/2,0),m_drawArea.bottomLeft() + QPoint(len/2,0));painter.drawEllipse(m_drawArea.center(),len/2,len/2);painter.drawEllipse(m_drawArea.center(),len/3,len/3);painter.drawEllipse(m_drawArea.center(),len/6,len/6);
在这里有个m_drawArea是用来描述绘制雷达的区域的。先确定这个绘制区域,更容易计算绘制的内容。 m_drawArea的大小在resizeEvent事件中确定。
void CRadar::resizeEvent(QResizeEvent *event)
{//以较短的边长作为绘制区域边长if(width() > height()){m_drawArea = QRect((width() - height())/2,0,height(),height());}else{m_drawArea = QRect(0,(height() - width())/2,width(),width());}m_drawArea.adjust(10,10,-10,-10);
}
为了确保雷达为圆形,我们以较短的边作为矩形的边长。然后使用adjust缩小一点。adjust前两个参数为左上角x和y的增量,后两个参数为右下角x和y的增量。
2.转动部分由一个扇形和一条直线组成。扇形使用了锥形渐变色。代码如下:
//转动部分//---//线qreal x = m_drawArea.center().x() + (qreal)len/2 * cos(-m_pieRotate*3.14159/180);qreal y = m_drawArea.center().y() + (qreal)len/2 * sin(-m_pieRotate*3.14159/180);painter.setPen(QPen(Qt::white));painter.drawLine(m_drawArea.center(),QPointF(x,y));//----//扇形QConicalGradient gradient;gradient.setCenter(m_drawArea.center());gradient.setAngle(m_pieRotate + 180); //渐变与旋转方向恰好相反,以扇形相反的边作为渐变角度。gradient.setColorAt(0.4,QColor(255,255,255,100)); //从渐变角度开始0.5 - 0.75为扇形区域,由于Int类型计算不精确,将范围扩大到0.4-0.8gradient.setColorAt(0.8,QColor(255,255,255,0));painter.setBrush(QBrush(gradient));painter.setPen(Qt::NoPen);painter.drawPie(m_drawArea,m_pieRotate*16,90*16);
直线的绘制很简单,只需要计算转动角度对应圆上的点的坐标即可。扇形的绘制也很简单。难点在于渐变色的应用,由于锥形渐变是逆时针的,而我们的雷达是顺时针的转动。所以要计算好扇形区域在渐变的哪个范围。这里设置了渐变角度为扇形角度旋转180度,那么扇形区域应该在渐变角度的0.5 - 0.75范围内。由于这里使用的是int类型,怕计算的不精确,将渐变颜色的范围设置大一些。
3.第三部分是随机闪烁的点,用来点缀。在这里使用了一个list存放点的坐标,另一个list存放这些点的颜色alapha值。使用一个定时器随机改变这些点的坐标值和alapha值。
void CRadar::timerEvent(QTimerEvent *event)
{if(m_timerId == event->timerId()){m_pieRotate -= 10;update();}else if(m_pointTimerId == event->timerId()){//随机更换装饰的点for(int i = 0; i < m_points.count(); ++i){int offsetX = rand()%m_drawArea.width();int offsetY = rand()%m_drawArea.width();int alapha = rand()%255;m_points.replace(i,QPoint(offsetX,offsetY) + m_drawArea.topLeft());m_pointsAlapha.replace(i,alapha);}update();}
}
第一个定时器是用来改变转动部分的角度的。第二个定时器才是用来改变闪烁点的。
cradar.h
#ifndef CRADAR_H
#define CRADAR_H/*************************************************
作者:fearlazy
博客:www.fearlazy.com
描述: 仿雷达扫描效果(Qt绘制学习实践)
**************************************************/#include class CRadar : public QWidget
{Q_OBJECT
public:explicit CRadar(QWidget *parent = nullptr);
protected:void paintEvent(QPaintEvent *event); //绘制事件void resizeEvent(QResizeEvent *event); //大小重置事件void timerEvent(QTimerEvent *event); //定时器事件
private:QRect m_drawArea; //绘制区域int m_pieRotate; //扇形旋转区域int m_timerId; //定时器IDint m_pointTimerId; //变更点定时器int m_nSpeed; //速度QList m_points; //绘制点QList<int> m_pointsAlapha; //绘制点颜色alapha值
};#endif // CRADAR_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = 0);~Widget();
};#endif // WIDGET_H
cradar.cpp
#include "cradar.h"
#include
#include
#include
#include CRadar::CRadar(QWidget *parent) : QWidget(parent)
{//初始化m_pieRotate = 0;m_timerId = -1;m_nSpeed = 50;m_points<;m_pointsAlapha<<100<<100<<100<<100<<100;//启动定时器m_timerId = startTimer(m_nSpeed);m_pointTimerId = startTimer(1200);
}void CRadar::paintEvent(QPaintEvent *event)
{QPainter painter(this);//抗锯齿painter.setRenderHint(QPainter::Antialiasing);//背景painter.fillRect(rect(),QColor(15,45,188));//边长int len = m_drawArea.width();//底盘(x轴、y轴和3个圆)painter.setPen(QPen(Qt::white));painter.drawLine(m_drawArea.topLeft() + QPoint(0,len/2),m_drawArea.topRight() + QPoint(0,len/2));painter.drawLine(m_drawArea.topLeft() + QPoint(len/2,0),m_drawArea.bottomLeft() + QPoint(len/2,0));painter.drawEllipse(m_drawArea.center(),len/2,len/2);painter.drawEllipse(m_drawArea.center(),len/3,len/3);painter.drawEllipse(m_drawArea.center(),len/6,len/6);//转动部分//---//线qreal x = m_drawArea.center().x() + (qreal)len/2 * cos(-m_pieRotate*3.14159/180);qreal y = m_drawArea.center().y() + (qreal)len/2 * sin(-m_pieRotate*3.14159/180);painter.setPen(QPen(Qt::white));painter.drawLine(m_drawArea.center(),QPointF(x,y));//----//扇形QConicalGradient gradient;gradient.setCenter(m_drawArea.center());gradient.setAngle(m_pieRotate + 180); //渐变与旋转方向恰好相反,以扇形相反的边作为渐变角度。gradient.setColorAt(0.4,QColor(255,255,255,100)); //从渐变角度开始0.5 - 0.75为扇形区域,由于Int类型计算不精确,将范围扩大到0.4-0.8gradient.setColorAt(0.8,QColor(255,255,255,0));painter.setBrush(QBrush(gradient));painter.setPen(Qt::NoPen);painter.drawPie(m_drawArea,m_pieRotate*16,90*16);//装饰-随机点for(int i = 0; i < m_points.count(); ++i){int colorAlaph = m_pointsAlapha.at(i);painter.setPen(QPen(QColor(255,255,255,colorAlaph),3));painter.drawPoint(m_points.at(i));}//更详细解释参考:http://fearlazy.com/index.php/post/31.html
}void CRadar::resizeEvent(QResizeEvent *event)
{//以较短的边长作为绘制区域边长if(width() > height()){m_drawArea = QRect((width() - height())/2,0,height(),height());}else{m_drawArea = QRect(0,(height() - width())/2,width(),width());}m_drawArea.adjust(10,10,-10,-10);
}void CRadar::timerEvent(QTimerEvent *event)
{if(m_timerId == event->timerId()){m_pieRotate -= 10;update();}else if(m_pointTimerId == event->timerId()){//随机更换装饰的点for(int i = 0; i < m_points.count(); ++i){int offsetX = rand()%m_drawArea.width();int offsetY = rand()%m_drawArea.width();int alapha = rand()%255;m_points.replace(i,QPoint(offsetX,offsetY) + m_drawArea.topLeft());m_pointsAlapha.replace(i,alapha);}update();}
}
main.cpp
#include "widget.h"
#include int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
widget.cpp
#include "widget.h"
#include "cradar.h"Widget::Widget(QWidget *parent): QWidget(parent)
{CRadar* radar = new CRadar(this);radar->setFixedSize(300,300);radar->move(50,50);
}Widget::~Widget()
{}
效果图:
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
