发布时间:2023-09-27 10:30
开始使用Qcharts画图,大数据性能极差。于是转用Customplot画图,主要进行数据的实时更新和大量数据的加载
采用子线程创建模拟数据,采用队列存储。
#pragma once
#include
#include
#include
#include
#include
#include
using namespace std;
class QTgui : public QThread
{
Q_OBJECT
signals:
void sigCurrentImage1(QVariant img);
public:
QTgui(QObject *parent = nullptr);
~QTgui();
std::thread * tthread;
void run();
void SetRandNum();
private:
int a;
QString data;
QMutex tex;
QMap<QString, QQueue<QPointF>> datamap;//key 设备名称 value 点
};
#include \"QTgui .h\"
#include
#include
#include
#include
#include
QTgui::QTgui(QObject *parent)
: QThread(parent)
{
a = 0;
}
QTgui ::~QTgui()
{
}
void QTgui::run()
{
qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
//point = new QQueue();
// 要想线程一直运行 就用 while 不会运行一次就结束了
while (1)
{
SetRandNum();
QVariant var;
var.setValue(datamap);
emit sigCurrentImage1(var);
this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
void QTgui::SetRandNum()
{
for (int i = 0; i < 1; i++)
{
for (int j = 0; j < 3600; j++)
{
QTime time(QTime::currentTime());
int nowtime = time.msecsSinceStartOfDay();
QPointF currentpoint = QPointF(nowtime, qrand() % 101);
if (datamap.count(QString::number(i)) > 0)
{
if (datamap[QString::number(i)].size() > 3600)
{
datamap[QString::number(i)].dequeue();
datamap[QString::number(i)].enqueue(currentpoint);
}
else
{
datamap[QString::number(i)].enqueue(currentpoint);
}
}
else
{
QQueue<QPointF> dataqueue;
dataqueue.enqueue(currentpoint);
datamap.insert(QString::number(i), dataqueue);
}
}
//QTime time(QTime::currentTime());
//int nowtime = time.msecsSinceStartOfDay();
//QPointF currentpoint = QPointF(nowtime, qrand() % 101);
//if (datamap.count(QString::number(i)) > 0)
//{
// if (datamap[QString::number(i)].size() > 1000000)
// {
// datamap[QString::number(i)].dequeue();
// datamap[QString::number(i)].enqueue(currentpoint);
// }
// else
// {
// datamap[QString::number(i)].enqueue(currentpoint);
// }
//}
//else
//{
// QQueue dataqueue;
// dataqueue.enqueue(currentpoint);
// datamap.insert(QString::number(i), dataqueue);
//}
auto aa = 0;
}
}
数据有坐标点和时间点2种,测试注释掉了时间点。
主要用于连接数据线程和UI槽函数的连接。
#pragma once
#include
#include
#include \"ui_QtWidgetsApplication7.h\"
#include \"QTgui .h\"
#include
#include
class QtWidgetsApplication7 : public QMainWindow
{
Q_OBJECT
public:
QtWidgetsApplication7(QWidget *parent = Q_NULLPTR);
void Init();
~QtWidgetsApplication7();
QTgui* g1;
signals:
void SendData(QMap<QString, QQueue<QPointF>> data);//发送数据
private:
Ui::QtWidgetsApplication7Class ui;
int a = 1;
private slots:
void slot2(QVariant data);
};
#include \"QtWidgetsApplication7.h\"
#include\"qcustomplot.h\"
#include\"LineChartTest.h\"
#if _MSC_VER >= 1600 //VS2015>VS>VS2010, MSVC VER= 10.0 -14.0 防止乱码
#pragma execution_character_set(\"utf-8\")
#endif
QtWidgetsApplication7::QtWidgetsApplication7(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
Init();
}
void QtWidgetsApplication7::Init()
{
g1 = new QTgui(this);
g1->start();
connect(g1, SIGNAL(sigCurrentImage1(QVariant)), this, SLOT(slot2(QVariant)));
LineChartTest *cht = new LineChartTest(this);
connect(this, SIGNAL(SendData(QMap<QString, QQueue<QPointF>>)), cht, SLOT(ShowData(QMap<QString, QQueue<QPointF>>)));
connect(this, SIGNAL(SendData(QMap<QString, QQueue<QPointF>>)), cht, SLOT(Run(QMap<QString, QQueue<QPointF>>)));
QVBoxLayout *layout3 = new QVBoxLayout();
layout3->addWidget(cht);
ui.widget->setLayout(layout3);
}
QtWidgetsApplication7::~QtWidgetsApplication7()
{
g1->terminate();//主动结束线程
g1->deleteLater();
}
void QtWidgetsApplication7::slot2(QVariant data)
{
ui.label->setText(QString::number(a++));
QMap<QString, QQueue<QPointF>> d=data.value<QMap<QString, QQueue<QPointF>>>();
SendData(d);
}
展示实时数据和更新界面。启用定时器更新界面。
#pragma once
#include
#include \"QTgui .h\"
#include \"ui_LineChartTest.h\"
#include \"QCustomPlot.h\"
using namespace std;
class LineChartTest : public QWidget
{
Q_OBJECT
public:
LineChartTest(QWidget *parent = Q_NULLPTR);
~LineChartTest();
void initPlotForm();
public slots:
void ShowData(QMap<QString, QQueue<QPointF>> a);
void Show_Plot();
void Run(QMap<QString, QQueue<QPointF>> data);
private:
Ui::LineChartTest ui;
int data;
void ShowChart();
QCustomPlot *customPlot;
QCPGraph *series[32];//最多可以设置曲线数量
QQueue<QPointF> point;
QTimer *timer;
bool status;//显示哪条折线
};
#include \"LineChartTest.h\"
#include
#include \"QCustomPlot.h\"
#pragma execution_character_set(\"utf-8\")
LineChartTest::LineChartTest(QWidget *parent)
: QWidget(parent), status(false)
{
ui.setupUi(this);
initPlotForm();
//定时器更新图表
timer = new QTimer();
timer->start(200);
connect(timer, SIGNAL(timeout()), this, SLOT(Show_Plot()));
QThread *thd = new QThread();
customPlot->moveToThread(thd);//其他图像操作放到子线程
thd->start();
}
void LineChartTest::ShowChart()
{
}
LineChartTest::~LineChartTest()
{
timer->deleteLater();
}
void LineChartTest::ShowData(QMap<QString, QQueue<QPointF>> getdata)
{
}
//初始化图表格式
void LineChartTest::initPlotForm()
{
//隐藏标题栏
this->setWindowFlags(Qt::FramelessWindowHint);
this->setWindowState((windowState()&~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowMaximized);
QVBoxLayout *layout = new QVBoxLayout();
customPlot = new QCustomPlot(this);
//QSharedPointer dateTicker(new QCPAxisTickerDateTime);//日期做X轴
//dateTicker->setDateTimeFormat(\"m:s\");//日期格式(可参考QDateTime::fromString()函数)
//customPlot->xAxis->setTicker(dateTicker);//设置X轴为时间轴
//customPlot->xAxis->setRange(0, 3601);
customPlot->xAxis->ticker()->setTickCount(37);//11个主刻度
customPlot->xAxis->setLabel(\"X轴\");//轴标签
customPlot->yAxis->setLabel(\"Y轴\");//轴标签
customPlot->yAxis->setRange(-30, 200);
customPlot->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);//x轴终点箭头图案
customPlot->xAxis->setLowerEnding(QCPLineEnding::esDisc);//x轴起点圆点图案
customPlot->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);//x轴起点圆点图案
layout->addWidget(customPlot);
customPlot->setOpenGl(true);
customPlot->addGraph(0)->setPen(QPen(Qt::red));
// 允许用户用鼠标拖动轴范围,用鼠标滚轮缩放,点击选择图形:
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
ui.widget->setLayout(layout);
}
void LineChartTest::Run(QMap<QString, QQueue<QPointF>> data)
{
int nowtime = QTime::currentTime().msecsSinceStartOfDay(); // 当前时间总的毫秒数
customPlot->clearGraphs(); //请清除所有
customPlot->xAxis->rescale(true);//调整X轴的范围,使之能显示出所有的曲线的X值
customPlot->yAxis->rescale(true);//调整Y轴的范围,使之能显示出所有的曲线的Y值
customPlot->xAxis->setRange(0, data[\"0\"].size());
//series->setObjectName(\"温度1\");
series[0]= customPlot->addGraph();
series[0]->setName(\"温度1\");
series[0]->setPen(QPen(Qt::red));
series[1] = customPlot->addGraph();
series[1]->setName(\"湿度1\");
series[1]->setPen(QPen(Qt::blue));
for (int i = 0; i < data[QString::number(0)].size(); i++)
{
//给曲线添加数据
//series->addData(data[QString::number(0)].at(i).x()*0.001, data[QString::number(0)].at(i).y());
series[0]->addData(i, data[QString::number(0)].at(i).y());
series[1]->addData(i, data[QString::number(0)].at(i).y()+50);
}
//this_thread::sleep_for(std::chrono::milliseconds(1));
}
//更新绘图 同时分别显示对应曲线
void LineChartTest::Show_Plot()
{
if (status)
{
for (int i = 0; i < 2; i++)
{
if (series[i]->name() == \"温度1\")
{
series[i]->setVisible(false);
}
}
status = !status;
}
else
{
for (int i = 0; i < 2; i++)
{
if (series[i]->name() == \"湿度1\")
{
series[i]->setVisible(false);
}
}
status = !status;
}
customPlot->replot(QCustomPlot::rpQueuedReplot);
}
下载地址:https://download.csdn.net/download/qq_38491692/85311194
本文主要介绍了一个基本的绘制曲线的流程,线程产生数据,定时更新。解决界面卡顿问题。