qcustomplot
QCustomPlot是Qt的一个小型第三方图表库,支持静态/动态曲线、柱状图、蜡烛图、频谱图等,使用起来也是非常的方便,这里也不过多的进行介绍了。
效果图
功能介绍
默认的绘图方式虽然方便,但长时间的执行会有较大的内存压力。为了避免这一问题采用操作缓存区的方式来存放数据,同时能让x,y轴动态调整保证线条的动态居中。
分配缓存区
while (m_draw->removeGraph(0));
m_bufferSize = size;
QSharedPointer<QCPGraphDataContainer> dataContainer = m_draw->addGraph()->data();
QVector<QCPGraphData> plotData(m_bufferSize);
for (size_t j = 0; j < m_bufferSize; j++)
{
plotData[j].key = j;
plotData[j].value = initialValue;
}
dataContainer->set(plotData, true);
m_draw->xAxis->setRange(0, m_bufferSize);
m_dataQueue.clear();
m_drawBuffer = m_draw->graph()->data().data();
增加数据
将数据存放入队列中
if (m_dataQueue.size() >= m_bufferSize)
m_dataQueue.dequeue();
m_dataQueue.enqueue(data);
开始绘图
if (m_lineTimer.isActive())
m_lineTimer.stop();
if (m_axisTimer.isActive())
m_axisTimer.stop();
m_lineTimer.start(lineRefreshTime);
m_axisTimer.start(axisRefreshTime);
绘图的定时器
size_t size = m_dataQueue.size();
for (size_t j = size - 1; j; --j)
{
QCPGraphData* buff = (QCPGraphData*)m_drawBuffer->at(j);
buff->value = m_dataQueue.at(j);
}
m_draw->replot(QCustomPlot::rpQueuedReplot);
动态改变Y轴
m_max = *std::max_element(m_dataQueue.begin(), m_dataQueue.end());
m_min = *std::min_element(m_dataQueue.begin(), m_dataQueue.end());
m_draw->xAxis->setRange(0, m_bufferSize);
if (m_max < 0)
m_draw->yAxis->setRange(m_min + m_min * m_magnification, m_max - m_max * m_magnification);
else
{
if (m_min > 0)
m_draw->yAxis->setRange(m_min - m_min * m_magnification, m_max + m_max * m_magnification);
else
m_draw->yAxis->setRange(m_min + m_min * m_magnification, m_max + m_max * m_magnification);
}
放大图层缩小图层
放大
if (m_magnification > 0.1)
m_magnification -= 0.1;
缩小
if (m_magnification < 5)
m_magnification += 0.1;
#全部代码
#pragma once
#include <QObject>
#include"qcustomplot.h"
#include<QTimer>
#include<QQueue>
class DynamicDraw : public QObject
{
Q_OBJECT
public:
DynamicDraw(QCustomPlot* customPlot, QObject* parent = nullptr);
~DynamicDraw();
void allotBuffer(u_short size, float initialValue = 0);
void addData(float data);
void startDraw(u_short lineRefreshTime = 30, u_short axisRefreshTime = 100);
void magnify();
void shrink();
private slots:
void on_refreshLine_timeOut();
void on_refreshAxis_timeOut();
private:
QCustomPlot* m_draw;
QTimer m_lineTimer;
QTimer m_axisTimer;
QQueue<float> m_dataQueue;
u_short m_bufferSize;
int m_max;
int m_min;
float m_magnification;
QCPGraphDataContainer* m_drawBuffer;
};
#include "DynamicDraw.h"
DynamicDraw::DynamicDraw(QCustomPlot* customPlot,QObject *parent)
: QObject(parent),m_draw(customPlot),m_bufferSize(0),m_magnification(1),m_max(0),m_min(0),m_drawBuffer(NULL)
{
connect(&m_lineTimer, &QTimer::timeout, this, &DynamicDraw::on_refreshLine_timeOut);
connect(&m_axisTimer, &QTimer::timeout, this, &DynamicDraw::on_refreshAxis_timeOut);
}
DynamicDraw::~DynamicDraw()
{
}
void DynamicDraw::allotBuffer(u_short size, float initialValue)
{
while (m_draw->removeGraph(0));
m_bufferSize = size;
QSharedPointer<QCPGraphDataContainer> dataContainer = m_draw->addGraph()->data();
QVector<QCPGraphData> plotData(m_bufferSize);
for (size_t j = 0; j < m_bufferSize; j++)
{
plotData[j].key = j;
plotData[j].value = initialValue;
}
dataContainer->set(plotData, true);
m_draw->xAxis->setRange(0, m_bufferSize);
m_dataQueue.clear();
m_drawBuffer = m_draw->graph()->data().data();
}
void DynamicDraw::addData(float data)
{
if (m_dataQueue.size() >= m_bufferSize)
m_dataQueue.dequeue();
m_dataQueue.enqueue(data);
}
void DynamicDraw::startDraw(u_short lineRefreshTime, u_short axisRefreshTime)
{
if (m_lineTimer.isActive())
m_lineTimer.stop();
if (m_axisTimer.isActive())
m_axisTimer.stop();
m_lineTimer.start(lineRefreshTime);
m_axisTimer.start(axisRefreshTime);
}
void DynamicDraw::magnify()
{
if (m_magnification > 0.1)
m_magnification -= 0.1;
}
void DynamicDraw::shrink()
{
if (m_magnification < 5)
m_magnification += 0.1;
}
void DynamicDraw::on_refreshLine_timeOut()
{
size_t size = m_dataQueue.size();
for (size_t j = size - 1; j; --j)
{
QCPGraphData* buff = (QCPGraphData*)m_drawBuffer->at(j);
buff->value = m_dataQueue.at(j);
}
m_draw->replot(QCustomPlot::rpQueuedReplot);
}
void DynamicDraw::on_refreshAxis_timeOut()
{
m_max = *std::max_element(m_dataQueue.begin(), m_dataQueue.end());
m_min = *std::min_element(m_dataQueue.begin(), m_dataQueue.end());
m_draw->xAxis->setRange(0, m_bufferSize);
if (m_max < 0)
m_draw->yAxis->setRange(m_min + m_min * m_magnification, m_max - m_max * m_magnification);
else
{
if (m_min > 0)
m_draw->yAxis->setRange(m_min - m_min * m_magnification, m_max + m_max * m_magnification);
else
m_draw->yAxis->setRange(m_min + m_min * m_magnification, m_max + m_max * m_magnification);
}
}
有更好的思路请在评论区指出