当前位置:   article > 正文

Qt总结之七:QPaintEvent绘制雷达图(二)_qt雷达p显

qt雷达p显

前言

这里使用另一套框架写的雷达扫描图

这里PaintEvent事件比上一个版本写的好,但是不喜欢Widget嵌套的方式,后续会把两个版本整合到一起。

 一、实现原理

雷达效果包括三个部分:背景、转动的扇形和闪烁的点。 
(1)背景的实现很简单,首先填充背景色,然后绘制横纵坐标轴以及三个同心圆。代码如下:

  1. //背景
  2. painter.fillRect(rect(),QColor(15,45,188));
  3. //边长
  4. int len = m_drawArea.width();
  5. //底盘(x轴、y轴和3个圆)
  6. painter.setPen(QPen(Qt::white));
  7. painter.drawLine(m_drawArea.topLeft() + QPoint(0,len/2),m_drawArea.topRight() + QPoint(0,len/2));
  8. painter.drawLine(m_drawArea.topLeft() + QPoint(len/2,0),m_drawArea.bottomLeft() + QPoint(len/2,0));
  9. painter.drawEllipse(m_drawArea.center(),len/2,len/2);
  10. painter.drawEllipse(m_drawArea.center(),len/3,len/3);
  11. painter.drawEllipse(m_drawArea.center(),len/6,len/6);

在这里有个m_drawArea是用来描述绘制雷达的区域的。先确定这个绘制区域,更容易计算绘制的内容。 m_drawArea的大小在resizeEvent事件中确定。

  1. void CRadar::resizeEvent(QResizeEvent *event)
  2. {
  3. //以较短的边长作为绘制区域边长
  4. if(width() > height())
  5. {
  6. m_drawArea = QRect((width() - height())/2,0,height(),height());
  7. }
  8. else
  9. {
  10. m_drawArea = QRect(0,(height() - width())/2,width(),width());
  11. }
  12. m_drawArea.adjust(10,10,-10,-10);
  13. }

为了确保雷达为圆形,我们以较短的边作为矩形的边长。然后使用adjust缩小一点。adjust前两个参数为左上角x和y的增量,后两个参数为右下角x和y的增量。

(2)转动部分由一个扇形和一条直线组成。扇形使用了锥形渐变色。代码如下:

  1. //转动部分
  2. //---//线
  3. qreal x = m_drawArea.center().x() + (qreal)len/2 * cos(-m_pieRotate*3.14159/180);
  4. qreal y = m_drawArea.center().y() + (qreal)len/2 * sin(-m_pieRotate*3.14159/180);
  5. painter.setPen(QPen(Qt::white));
  6. painter.drawLine(m_drawArea.center(),QPointF(x,y));
  7. //----//扇形
  8. QConicalGradient gradient;
  9. gradient.setCenter(m_drawArea.center());
  10. gradient.setAngle(m_pieRotate + 180); //渐变与旋转方向恰好相反,以扇形相反的边作为渐变角度。
  11. gradient.setColorAt(0.4,QColor(255,255,255,100)); //从渐变角度开始0.5 - 0.75为扇形区域,由于Int类型计算不精确,将范围扩大到0.4-0.8
  12. gradient.setColorAt(0.8,QColor(255,255,255,0));
  13. painter.setBrush(QBrush(gradient));
  14. painter.setPen(Qt::NoPen);
  15. painter.drawPie(m_drawArea,m_pieRotate*16,90*16);

直线的绘制很简单,只需要计算转动角度对应圆上的点的坐标即可。扇形的绘制也很简单。难点在于渐变色的应用,由于锥形渐变是逆时针的,而我们的雷达是顺时针的转动。所以要计算好扇形区域在渐变的哪个范围。这里设置了渐变角度为扇形角度旋转180度,那么扇形区域应该在渐变角度的0.5 - 0.75范围内。由于这里使用的是int类型,怕计算的不精确,将渐变颜色的范围设置大一些。

(3)第三部分是随机闪烁的点,用来点缀。在这里使用了一个list存放点的坐标,另一个list存放这些点的颜色alapha值。使用一个定时器随机改变这些点的坐标值和alapha值。

  1. void CRadar::timerEvent(QTimerEvent *event)
  2. {
  3. if(m_timerId == event->timerId())
  4. {
  5. m_pieRotate -= 10;
  6. update();
  7. }
  8. else if(m_pointTimerId == event->timerId())
  9. {
  10. //随机更换装饰的点
  11. for(int i = 0; i < m_points.count(); ++i)
  12. {
  13. int offsetX = rand()%m_drawArea.width();
  14. int offsetY = rand()%m_drawArea.width();
  15. int alapha = rand()%255;
  16. m_points.replace(i,QPoint(offsetX,offsetY) + m_drawArea.topLeft());
  17. m_pointsAlapha.replace(i,alapha);
  18. }
  19. update();
  20. }
  21. }

第一个定时器是用来改变转动部分的角度的。第二个定时器才是用来改变闪烁点的。


二、代码区

radar.h

  1. #ifndef RADAR_H
  2. #define RADAR_H
  3. #include <QWidget>
  4. class Radar : public QWidget
  5. {
  6. Q_OBJECT
  7. public:
  8. Radar(QWidget *parent);
  9. ~Radar();
  10. protected:
  11. void paintEvent(QPaintEvent *event); //绘制事件
  12. void resizeEvent(QResizeEvent *event); //大小重置事件
  13. void timerEvent(QTimerEvent *event); //定时器事件
  14. private:
  15. QRect m_drawArea; //绘制区域
  16. int m_pieRotate; //扇形旋转区域
  17. int m_timerId; //定时器ID
  18. int m_pointTimerId; //变更点定时器
  19. int m_nSpeed; //速度
  20. QList<QPoint> m_points; //绘制点
  21. QList<int> m_pointsAlapha; //绘制点颜色alapha值
  22. };
  23. #endif // RADAR_H

radarscannice.h

  1. #ifndef RADARSCANNICE_H
  2. #define RADARSCANNICE_H
  3. #include <QtWidgets/QWidget>
  4. #include "ui_radarscannice.h"
  5. class RadarScanNice : public QWidget
  6. {
  7. Q_OBJECT
  8. public:
  9. RadarScanNice(QWidget *parent = 0);
  10. ~RadarScanNice();
  11. private:
  12. Ui::RadarScanNiceClass ui;
  13. };
  14. #endif // RADARSCANNICE_H

radar.cpp

  1. #include "radar.h"
  2. #include <QPainter>
  3. #include <QTimerEvent>
  4. #include <QConicalGradient>
  5. #include <qDebug>
  6. Radar::Radar(QWidget *parent)
  7. : QWidget(parent)
  8. {
  9. //初始化
  10. m_pieRotate = 0;
  11. m_timerId = -1;
  12. m_nSpeed = 50;
  13. m_points << QPoint() << QPoint() << QPoint() << QPoint() << QPoint();
  14. m_pointsAlapha << 100 << 100 << 100 << 100 << 100;
  15. //启动定时器
  16. m_timerId = startTimer(m_nSpeed);
  17. m_pointTimerId = startTimer(1200);
  18. }
  19. Radar::~Radar()
  20. {
  21. }
  22. void Radar::paintEvent(QPaintEvent *event)
  23. {
  24. QPainter painter(this);
  25. //抗锯齿
  26. painter.setRenderHint(QPainter::Antialiasing);
  27. //背景
  28. painter.fillRect(rect(), QColor(15, 45, 188));
  29. //边长
  30. int len = m_drawArea.width();
  31. //底盘(x轴、y轴和3个圆)
  32. painter.setPen(QPen(Qt::white));
  33. painter.drawLine(m_drawArea.topLeft() + QPoint(0, len / 2), m_drawArea.topRight() + QPoint(0, len / 2));
  34. painter.drawLine(m_drawArea.topLeft() + QPoint(len / 2, 0), m_drawArea.bottomLeft() + QPoint(len / 2, 0));
  35. painter.drawEllipse(m_drawArea.center(), len / 2, len / 2);
  36. painter.drawEllipse(m_drawArea.center(), len / 3, len / 3);
  37. painter.drawEllipse(m_drawArea.center(), len / 6, len / 6);
  38. //转动部分
  39. //---//线
  40. qreal x = m_drawArea.center().x() + (qreal)len / 2 * cos(-m_pieRotate*3.14159 / 180);
  41. qreal y = m_drawArea.center().y() + (qreal)len / 2 * sin(-m_pieRotate*3.14159 / 180);
  42. painter.setPen(QPen(Qt::white));
  43. painter.drawLine(m_drawArea.center(), QPointF(x, y));
  44. //----//扇形
  45. QConicalGradient gradient;
  46. gradient.setCenter(m_drawArea.center());
  47. gradient.setAngle(m_pieRotate + 180); //渐变与旋转方向恰好相反,以扇形相反的边作为渐变角度。
  48. gradient.setColorAt(0.4, QColor(255, 255, 255, 100)); //从渐变角度开始0.5 - 0.75为扇形区域,由于Int类型计算不精确,将范围扩大到0.4-0.8
  49. gradient.setColorAt(0.8, QColor(255, 255, 255, 0));
  50. painter.setBrush(QBrush(gradient));
  51. painter.setPen(Qt::NoPen);
  52. painter.drawPie(m_drawArea, m_pieRotate * 16, 90 * 16);
  53. //装饰-随机点
  54. for (int i = 0; i < m_points.count(); ++i)
  55. {
  56. int colorAlaph = m_pointsAlapha.at(i);
  57. painter.setPen(QPen(QColor(255, 255, 255, colorAlaph), 3));
  58. painter.drawPoint(m_points.at(i));
  59. }
  60. }
  61. void Radar::resizeEvent(QResizeEvent *event)
  62. {
  63. //以较短的边长作为绘制区域边长
  64. if (width() > height())
  65. {
  66. m_drawArea = QRect((width() - height()) / 2, 0, height(), height());
  67. }
  68. else
  69. {
  70. m_drawArea = QRect(0, (height() - width()) / 2, width(), width());
  71. }
  72. m_drawArea.adjust(10, 10, -10, -10);
  73. }
  74. void Radar::timerEvent(QTimerEvent *event)
  75. {
  76. if (m_timerId == event->timerId())
  77. {
  78. m_pieRotate -= 10;
  79. update();
  80. }
  81. else if (m_pointTimerId == event->timerId())
  82. {
  83. //随机更换装饰的点
  84. for (int i = 0; i < m_points.count(); ++i)
  85. {
  86. int offsetX = rand() % m_drawArea.width();
  87. int offsetY = rand() % m_drawArea.width();
  88. int alapha = rand() % 255;
  89. m_points.replace(i, QPoint(offsetX, offsetY) + m_drawArea.topLeft());
  90. m_pointsAlapha.replace(i, alapha);
  91. }
  92. update();
  93. }
  94. }

 

radarscannice.cpp

  1. #include "radarscannice.h"
  2. #include "radar.h"
  3. RadarScanNice::RadarScanNice(QWidget *parent)
  4. : QWidget(parent)
  5. {
  6. ui.setupUi(this);
  7. Radar* radar = new Radar(this);
  8. radar->setFixedSize(300, 300);
  9. radar->move(150, 50);
  10. }
  11. RadarScanNice::~RadarScanNice()
  12. {
  13. }

main.cpp

  1. #include "radarscannice.h"
  2. #include <QtWidgets/QApplication>
  3. int main(int argc, char *argv[])
  4. {
  5. QApplication a(argc, argv);
  6. RadarScanNice w;
  7. w.show();
  8. return a.exec();
  9. }

 


效果图:

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号