效果图
头文件
#ifndef QWHRADARSCAN_H
#define QWHRADARSCAN_H
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QList>
#include <QTimer>
#include <QColor>
class QWHRadarScan : public QWidget
{
Q_OBJECT
public:
struct Mark
{
int posX;
int posY;
int angle;
QString name;
};
explicit QWHRadarScan(QWidget *parent = nullptr);
~QWHRadarScan();
void setMarks(QList<Mark> marks);
QList<Mark> getMarks();
protected:
void paintEvent(QPaintEvent *event);
void drawBgArcs(QPainter *painter);
void drawScale(QPainter *painter);
void drawScaleNum(QPainter *painter);
void drawMarks(QPainter *painter);
void drawScan(QPainter *painter);
private:
double degreeToArc(double angle);
double distance(QPointF p1, QPointF p2);
private slots:
void Scanning();
signals:
public slots:
private:
int m_arcs; //圆弧数量
int m_curAngle; //当前扫描角度
int m_scanAngle; //扫描扇区角度
bool m_loop; //是否进入下次循环
bool m_refresh; //下次扫描是否清空从来
bool m_showText; //是否显示目标名称
bool m_showScale; //是否显示刻盘
int m_kilometers; //雷达扫描半径:千米
int m_scaleRotate; //雷达外围刻度旋转角度,正北方向刻度
QColor m_markColor; //目标颜色
QColor m_arcColor; //弧线和扫描区域颜色
QColor m_bgColor; //背景颜色
QColor m_scaleColor; //刻盘颜色
QList<Mark> m_listMarks; //存储目标
QTimer *m_timer; //定时器绘制
};
#endif // QWHRADARSCAN_H
核心代码
void QWHRadarScan::paintEvent(QPaintEvent *event)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height);
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.translate(width / 2, height / 2);
painter.scale(side / 200, side / 200);
//绘制背景
drawBgArcs(&painter);
if (m_showScale)
{
//绘制刻度线
drawScale(&painter);
//绘制刻度
drawScaleNum(&painter);
}
//绘制标记
drawMarks(&painter);
//绘制扫描
drawScan(&painter);
}
void QWHRadarScan::drawBgArcs(QPainter *painter)
{
painter->save();
painter->setBrush(m_bgColor);
painter->drawRect(-100, -100, 200, 200);
QPen pen(Qt::green, 1, Qt::SolidLine);
painter->setPen(pen);
QFont font;
font.setPixelSize(5);
painter->setFont(font);
for (int i = 1; i <= m_arcs; i++)
{
int radius = i * 84.0 / m_arcs;
QRect rect(-radius, -radius, radius * 2, radius * 2);
painter->drawArc(rect, 0 * 16, 360 * 16);
}
painter->drawLine(0, -84, 0, 84);
painter->drawLine(-84, 0, 84, 0);
#if 0
//显示距离
for (int i = 1; i <= 5; i++)
{
QString text = QString::number(m_kilometers * i * 1.0 / 5, 'f', 0);
int textWidth = fontMetrics().width(text);
int textHeight = fontMetrics().height();
painter->drawText(-textWidth / 2, 84.0 * i / 5 - textHeight / 2, textWidth, textHeight, Qt::AlignCenter, text);
}
#endif
painter->restore();
}
void QWHRadarScan::drawScale(QPainter *painter)
{
painter->save();
int radius = 86;
QPen pen(m_scaleColor);
int rotate = 180 + 360 - m_scaleRotate - 1;
painter->rotate(rotate);
for (int i = 0; i < 360; i++)
{
painter->rotate(1);
if (i % 5 == 0)
{
if (i % 10 == 0)
{
pen.setWidthF(0.7);
painter->setPen(pen);
painter->drawLine(QPoint(0, 84), QPoint(0, radius + 2));
}
else
{
pen.setWidthF(0.5);
painter->setPen(pen);
painter->drawLine(QPoint(0, 84), QPoint(0, radius + 1));
}
}
else
{
pen.setWidthF(0.4);
painter->setPen(pen);
painter->drawLine(QPoint(0, 84), QPoint(0, radius));
}
}
painter->restore();
}
void QWHRadarScan::drawScaleNum(QPainter *painter)
{
painter->save();
int radius = 93;
QPen pen(m_scaleColor);
QFont font;
font.setPixelSize(4);
painter->setFont(font);
int northAngle = 90;
int text = m_scaleRotate;
for (int i = m_scaleRotate; i < m_scaleRotate + 360; i++)
{
if (i % 10 == 0)
{
int x = radius * qCos(degreeToArc(northAngle));
int y = radius * qSin(degreeToArc(northAngle));
QPoint p(x, y);
text = (text >= 360) ? 0 : text;
QString strText = QString::number(text);
int textWidth = fontMetrics().width(strText);
int textHeight = fontMetrics().height();
painter->setPen(pen);
painter->drawText(x - textWidth / 8, -y + textHeight / 15, strText);
}
northAngle -= 1;
text++;
}
pen.setColor(Qt::white);
font.setPixelSize(6);
painter->setFont(font);
painter->setPen(pen);
painter->drawText(QPointF(-1, -91), QString("N"));
painter->drawText(QPointF(92, 2), QString("E"));
painter->drawText(QPointF(-1, 94), QString("S"));
painter->drawText(QPointF(-96, 2), QString("W"));
painter->restore();
}
void QWHRadarScan::drawMarks(QPainter *painter)
{
painter->save();
if (m_listMarks.count() <= 0)
{
return;
}
QPen pen(m_markColor, 5, Qt::SolidLine);
pen.setCapStyle(Qt::RoundCap);
painter->setPen(pen);
//扫描扇区(浓) 对应的 坐标轴角度
double realAngle = 360 - m_curAngle;
if (m_loop)
{
//第一圈扫描完后清空标记,重新显示
if (m_refresh)
{
for (int i = 0; i < m_listMarks.count(); i++)
{
QPoint p = QPoint(m_listMarks[i].posX, m_listMarks[i].posY);
if (distance(p, QPoint(0, 0)) < m_kilometers)
{
if (m_listMarks[i].angle > realAngle)
{
//绘图区域半径为100, 选取84长度作为雷达扫描的绘图区域
int posX = m_listMarks[i].posX * 1.0 / m_kilometers * 84.0;
int posY = -m_listMarks[i].posY * 1.0 / m_kilometers * 84.0;
painter->drawPoint(posX, posY);
if (m_showText)
{
int width = fontMetrics().width(m_listMarks[i].name);
int height = fontMetrics().height();
painter->drawText(posX - width / 2, posY - height / 4, m_listMarks[i].name);
}
}
}
}
}
else
{
for (int i = 0; i < m_listMarks.count(); i++)
{
QPoint p = QPoint(m_listMarks[i].posX, m_listMarks[i].posY);
if (distance(p, QPoint(0, 0)) < m_kilometers)
{
int posX = m_listMarks[i].posX * 1.0 / m_kilometers * 84.0;
int posY = -m_listMarks[i].posY * 1.0 / m_kilometers * 84.0;
painter->drawPoint(posX, posY);
if (m_showText)
{
int width = fontMetrics().width(m_listMarks[i].name);
int height = fontMetrics().height();
painter->drawText(posX - width / 2, posY - height / 4, m_listMarks[i].name);
}
}
}
}
}
else
{
for (int i = 0; i < m_listMarks.count(); i++)
{
QPoint p = QPoint(m_listMarks[i].posX, m_listMarks[i].posY);
if (distance(p, QPoint(0, 0)) < m_kilometers)
{
if (m_listMarks[i].angle > realAngle)
{
int posX = m_listMarks[i].posX * 1.0 / m_kilometers * 84.0;
int posY = -m_listMarks[i].posY * 1.0 / m_kilometers * 84.0;
painter->drawPoint(posX, posY);
if (m_showText)
{
int width = fontMetrics().width(m_listMarks[i].name);
int height = fontMetrics().height();
painter->drawText(posX - width / 2, posY - height / 4, m_listMarks[i].name);
}
}
}
}
}
painter->restore();
}
void QWHRadarScan::drawScan(QPainter *painter)
{
painter->save();
painter->rotate(m_curAngle);
QColor color1(m_arcColor);
color1.setAlpha(255);
QColor color2(m_arcColor);
color2.setAlpha(0);
QConicalGradient cg;
cg.setColorAt(0, color1);
cg.setColorAt(m_scanAngle * 1.0 / 360 , color2);
painter->setBrush(cg);
QRect rect(-84, -84, 168, 168);
painter->setPen(Qt::NoPen);
painter->drawPie(rect, 0 * 16, m_scanAngle * 16);
painter->restore();
}