1. 程式人生 > >QT之 QChart 顯示實時動態曲線(模擬資料採集過程)

QT之 QChart 顯示實時動態曲線(模擬資料採集過程)

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();
}