QT之 QChart 顯示實時動態曲線(模擬資料採集過程)
阿新 • • 發佈:2019-02-16
Qt 5.7 後提供了 charts 模組,使用 QSplineSeries 就能很輕鬆的實現平滑曲線了,而且效果很好,但是需要注意一點的是,免費版的 Qt 中 charts 模組是 GPL 協議的。
效果如下,隨著時間變化,曲線會從右向左移動
.h 程式碼:
#ifndef REALTIMECURVEQCHARTWIDGET_H
#define REALTIMECURVEQCHARTWIDGET_H
#include
#include
#include
#include
#include
#include
using namespace QtCharts;
class RealTimeCurveQChartWidget : public QWidget {
Q_OBJECT
public:
explicit RealTimeCurveQChartWidget(QWidget *parent = 0);
~RealTimeCurveQChartWidget();
protected:
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
private:
/**
* 接收到資料來源傳送來的資料,資料來源可以下位機,採集卡,感測器等。
*/
void dataReceived(int value);
int timerId;
int maxSize; // data 最多儲存 maxSize 個元素
int maxValue; // 業務資料的最大值
QList data; // 儲存業務資料的 list
QChart *chart;
QChartView *chartView;
QSplineSeries *splineSeries;
QScatterSeries *scatterSeries;
};
#endif // REALTIMECURVEQCHARTWIDGET_H
.CPP程式碼:
#include "RealTimeCurveQChartWidget.h"
#include
#include
RealTimeCurveQChartWidget::RealTimeCurveQChartWidget(QWidget *parent) : QWidget(parent) {
maxSize = 31; // 只儲存最新的 31 個數據
maxValue = 100; // 資料的最大值為 100,因為我們生成的隨機數為 [0, 100]
timerId = startTimer(200);
qsrand(QDateTime::currentDateTime().toTime_t());
splineSeries = new QSplineSeries();
scatterSeries = new QScatterSeries();
scatterSeries->setMarkerSize(8);
// 預先分配座標,這樣在 dataReceived 中直接替換座標了
for (int i = 0; i append(i * 10, -10);
scatterSeries->append(i * 10, -10);
}
chart = new QChart();
chart->addSeries(splineSeries);
chart->addSeries(scatterSeries);
chart->legend()->hide();
chart->setTitle("實時動態曲線");
chart->createDefaultAxes();
chart->axisY()->setRange(0, maxValue);
chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QHBoxLayout *layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(chartView);
setLayout(layout);
}
RealTimeCurveQChartWidget::~RealTimeCurveQChartWidget() {
}
void RealTimeCurveQChartWidget::timerEvent(QTimerEvent *event) {
if (event->timerId() == timerId) {
// 模擬不停的接收到新資料
int newData = qrand() % (maxValue + 1);
dataReceived(newData);
}
}
void RealTimeCurveQChartWidget::dataReceived(int value) {
data maxSize) {
data.removeFirst();
}
if (isVisible()) {
// 介面被隱藏後就沒有必要繪製資料的曲線了
// 替換曲線中現有資料
int delta = maxSize - data.size();
for (int i = 0; i replace(delta+i, splineSeries->at(delta+i).x(), data.at(i));
scatterSeries->replace(delta+i, scatterSeries->at(delta+i).x(), data.at(i));
}
}
}
可能需要注意的可能就是 x 座標的生成,因為資料是定時收到的,而且就只是一個數值,沒有座標資訊,所以我們把其作為 y 座標,x 座標則為每隔 10 個畫素就生成一個 x 座標,這樣在得到新的資料後,把資料一個挨一個的重新賦值給 series 就可以了,當然 x 座標變化也是 0, 10, 20, …, 100, …,這裡我們使用 replace() 函式來處理。
#include "RealTimeCurveQChartWidget.h"
#include
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
RealTimeCurveQChartWidget w;
w.show();
return a.exec();
}