Qt画的雷达图demo,多线程不断生成警示数据
运行结果
雷达
实现代码
h文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QThread>
#include <QTimer>
#include <QVector>
#include <QPointF>
class AnomalyDetectionThread;
class RadarChart : public QWidget
{
Q_OBJECT
public:
explicit RadarChart(QWidget *parent = nullptr);
~RadarChart();
protected:
void paintEvent(QPaintEvent *event) override;
private slots:
void onAnomalyDetected(int angle);
void updateScanAngle();
private:
void drawRadarBackground(QPainter &painter);
void drawScanLine(QPainter &painter);
void drawAnomalies(QPainter &painter);
AnomalyDetectionThread *anomalyThread;
QVector<int> anomalies;
QTimer *scanTimer;
int scanAngle;
};
class AnomalyDetectionThread : public QThread
{
Q_OBJECT
public:
AnomalyDetectionThread(QObject *parent = nullptr);
signals:
void anomalyDetected(int angle);
protected:
void run() override;
};
#endif // WIDGET_H
c文件
#include "widget.h"
#include <QPainter>
#include <QtMath>
#include <QRandomGenerator>
RadarChart::RadarChart(QWidget *parent) : QWidget(parent)
{
setFixedSize(400, 400);
// 启动异常检测线程
anomalyThread = new AnomalyDetectionThread(this);
connect(anomalyThread, &AnomalyDetectionThread::anomalyDetected, this, &RadarChart::onAnomalyDetected);
anomalyThread->start();
// 初始化扫描定时器
scanTimer = new QTimer(this);
connect(scanTimer, &QTimer::timeout, this, &RadarChart::updateScanAngle);
scanTimer->start(20); // 每 20 毫秒更新一次扫描角度
scanAngle = 0;
}
RadarChart::~RadarChart()
{
anomalyThread->requestInterruption();
anomalyThread->wait();
}
void RadarChart::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 绘制雷达图背景
drawRadarBackground(painter);
// 绘制扫描线
drawScanLine(painter);
// 绘制检测到的异常
drawAnomalies(painter);
}
void RadarChart::onAnomalyDetected(int angle)
{
anomalies.append(angle);
if (anomalies.size() > 10) { // 限制异常点的数量
anomalies.removeFirst();
}
update();
}
void RadarChart::updateScanAngle()
{
scanAngle = (scanAngle + 2) % 360; // 每次增加 2 度
update();
}
void RadarChart::drawRadarBackground(QPainter &painter)
{
int centerX = width() / 2;
int centerY = height() / 2;
int radius = qMin(width(), height()) / 2 - 20;
// 绘制雷达图的网格
painter.setPen(QPen(Qt::cyan, 1));
for (int i = 1; i <= 5; ++i) {
int currentRadius = radius * i / 5;
painter.drawEllipse(centerX - currentRadius, centerY - currentRadius, 2 * currentRadius, 2 * currentRadius);
}
// 绘制雷达图的射线
painter.setPen(QPen(Qt::cyan, 2));
for (int i = 0; i < 360; i += 30) {
double rad = qDegreesToRadians(static_cast<double>(i));
int x = centerX + radius * qCos(rad);
int y = centerY + radius * qSin(rad);
painter.drawLine(centerX, centerY, x, y);
}
}
void RadarChart::drawScanLine(QPainter &painter)
{
int centerX = width() / 2;
int centerY = height() / 2;
int radius = qMin(width(), height()) / 2 - 20;
double rad = qDegreesToRadians(static_cast<double>(scanAngle));
int x = centerX + radius * qCos(rad);
int y = centerY + radius * qSin(rad);
painter.setPen(QPen(Qt::yellow, 2));
painter.drawLine(centerX, centerY, x, y);
}
void RadarChart::drawAnomalies(QPainter &painter)
{
int centerX = width() / 2;
int centerY = height() / 2;
int radius = qMin(width(), height()) / 2 - 20;
painter.setPen(QPen(Qt::red, 5));
for (int angle : anomalies) {
double rad = qDegreesToRadians(static_cast<double>(angle));
int x = centerX + radius * qCos(rad);
int y = centerY + radius * qSin(rad);
painter.drawPoint(x, y);
}
}
AnomalyDetectionThread::AnomalyDetectionThread(QObject *parent) : QThread(parent)
{
}
void AnomalyDetectionThread::run()
{
while (!isInterruptionRequested()) {
int angle = QRandomGenerator::global()->bounded(360);
emit anomalyDetected(angle);
msleep(500); // 每 500 毫秒生成一个新的异常点
}
}
希望对大家有所帮助