如何使用Qt實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)動(dòng)態(tài)繪制的折線圖效果
基于Qt的 QChartView
和定時(shí)器來(lái)動(dòng)態(tài)繪制折線圖。它通過(guò)動(dòng)畫(huà)的方式逐步將數(shù)據(jù)點(diǎn)添加到圖表上,并動(dòng)態(tài)更新坐標(biāo)軸的范圍,提供了一個(gè)可以實(shí)時(shí)更新數(shù)據(jù)的折線圖應(yīng)用。以下是對(duì)代碼的詳細(xì)介紹及其功能解析:
代碼概述
該程序使用Qt的 QChartView
作為圖表繪制的基礎(chǔ),結(jié)合 QLineSeries
或 QSplineSeries
來(lái)繪制折線或樣條曲線。程序通過(guò)定時(shí)器 (QTimer
) 控制數(shù)據(jù)點(diǎn)的動(dòng)態(tài)繪制,并在繪圖過(guò)程中實(shí)時(shí)更新坐標(biāo)軸的顯示范圍。
主要功能
- 動(dòng)態(tài)創(chuàng)建系列:可以動(dòng)態(tài)創(chuàng)建多個(gè)曲線系列(
QLineSeries
或QSplineSeries
),每個(gè)系列對(duì)應(yīng)一條折線或樣條曲線。 - 動(dòng)態(tài)添加數(shù)據(jù)點(diǎn):通過(guò)
addPointAnimated()
函數(shù),可以為每個(gè)系列動(dòng)態(tài)添加數(shù)據(jù)點(diǎn),并通過(guò)動(dòng)畫(huà)效果逐步連接新數(shù)據(jù)點(diǎn)。 - 定時(shí)更新:使用
QTimer
每隔一段時(shí)間調(diào)用animateDrawing()
函數(shù),逐步將新點(diǎn)連接到已有的曲線上。 - 自動(dòng)調(diào)整坐標(biāo)軸范圍:在繪制過(guò)程中,如果新點(diǎn)超出了當(dāng)前坐標(biāo)軸范圍,坐標(biāo)軸會(huì)自動(dòng)調(diào)整以適應(yīng)新的數(shù)據(jù)點(diǎn)。
代碼結(jié)構(gòu)
1. DynamicChart
類(lèi)構(gòu)造函數(shù)
DynamicChart::DynamicChart(QWidget *parent) : QChartView(new QChart(), parent), m_chart(this->chart()) { m_chart->setTitle("Dynamic Data Plot"); m_chart->legend()->hide(); setRenderHint(QPainter::Antialiasing); // 設(shè)置圖表主題和隱藏圖例 m_chart->setTheme(QChart::ChartTheme::ChartThemeDark); // 創(chuàng)建共用的坐標(biāo)軸 axisX = new QValueAxis(); axisX->setRange(0, 100); m_chart->addAxis(axisX, Qt::AlignBottom); axisY = new QValueAxis(); axisY->setRange(0, 100); m_chart->addAxis(axisY, Qt::AlignLeft); // 設(shè)置定時(shí)器 connect(&timer, &QTimer::timeout, this, &DynamicChart::animateDrawing); timer.setInterval(30); // 動(dòng)畫(huà)更新間隔為30毫秒 resize(500,500); }
該構(gòu)造函數(shù)中設(shè)置了圖表的主題、坐標(biāo)軸、以及定時(shí)器,定時(shí)器的作用是每隔30毫秒觸發(fā) animateDrawing()
函數(shù),用于動(dòng)態(tài)繪制數(shù)據(jù)。
2. createSeries()
函數(shù)
void DynamicChart::createSeries(int seriesId, const QString &name) { #ifdef LINE QLineSeries *series = new QLineSeries(); #else QSplineSeries *series = new QSplineSeries(); #endif series->setName(name); m_chart->addSeries(series); // 使用共用的坐標(biāo)軸 series->attachAxis(axisX); series->attachAxis(axisY); seriesMap.insert(seriesId, series); }
該函數(shù)負(fù)責(zé)創(chuàng)建新的系列(折線或樣條曲線),并將其添加到圖表中。 seriesId
用于標(biāo)識(shí)不同的曲線,name
則用于顯示系列的名稱。系列將共享同一套坐標(biāo)軸。
3. addPointAnimated()
函數(shù)
void DynamicChart::addPointAnimated(int seriesId, const QPointF &point) { if (!seriesMap.contains(seriesId)) return; #ifdef LINE QLineSeries *series = seriesMap[seriesId]; #else QSplineSeries *series =seriesMap[seriesId]; #endif if (!series->points().isEmpty()) { lastPoint = series->points().last(); } else { lastPoint = point; // 第一個(gè)點(diǎn)直接添加 series->append(point); } newPoint = point; currentSeriesId = seriesId; currentStep = 0; stepsCount = 10; // 分10步完成連線 timer.start(); }
該函數(shù)用于為指定的系列添加新點(diǎn),并通過(guò)動(dòng)畫(huà)效果使新點(diǎn)逐步出現(xiàn)在圖表上。它會(huì)計(jì)算新點(diǎn)與最后一個(gè)點(diǎn)之間的插值,并逐步繪制曲線。
4. animateDrawing()
函數(shù)
void DynamicChart::animateDrawing() { #ifdef LINE QLineSeries *series = seriesMap[currentSeriesId]; #else QSplineSeries *series =seriesMap[currentSeriesId]; #endif if (currentStep >= stepsCount) { timer.stop(); series->append(newPoint); return; } qreal x = lastPoint.x() + (newPoint.x() - lastPoint.x()) * currentStep / stepsCount; qreal y = lastPoint.y() + (newPoint.y() - lastPoint.y()) * currentStep / stepsCount; series->append(x, y); // 動(dòng)態(tài)更新坐標(biāo)軸 if (x > axisX->max()) { axisX->setMax(x + 10); } if (y > axisY->max() || y < axisY->min()) { axisY->setMax(qMax(y + 10, axisY->max())); axisY->setMin(qMin(y - 10, axisY->min())); } currentStep++; }
該函數(shù)實(shí)現(xiàn)了通過(guò)定時(shí)器觸發(fā)的動(dòng)態(tài)繪制。它逐步將新點(diǎn)與前一個(gè)點(diǎn)連接,并動(dòng)態(tài)調(diào)整坐標(biāo)軸的范圍以適應(yīng)新增數(shù)據(jù)。
主窗口邏輯
最后的代碼片段展示了如何使用 DynamicChart
類(lèi)創(chuàng)建一個(gè)包含多個(gè)曲線的圖表,并通過(guò)按鈕控制定時(shí)器的啟動(dòng)與停止:
setMinimumSize(QSize(800,500)); chartView = new DynamicChart(this); chartView->createSeries(1, "Test Series 1"); chartView->createSeries(2, "Test Series 2"); chartView->createSeries(3, "Test Series 3"); chartView->createSeries(4, "Test Series 4"); QTimer *timer = new QTimer; connect(timer, &QTimer::timeout, this, [=]() { int m_id = QRandomGenerator::global()->bounded(1, 5); chartView->addPointAnimated(m_id, QPointF(m_index++, QRandomGenerator::global()->bounded(100))); }); startButton = new QRadioButton("StartDrawing", this); connect(startButton, &QRadioButton::clicked, [=](bool arg) { if (arg) timer->start(100); else timer->stop(); });
通過(guò) QRadioButton
控制定時(shí)器的啟停,點(diǎn)擊按鈕后,程序?qū)㈤_(kāi)始在圖表上隨機(jī)添加點(diǎn),并動(dòng)態(tài)繪制折線或樣條曲線。
結(jié)論
此程序通過(guò)Qt的 QChartView
和定時(shí)器,實(shí)現(xiàn)了一個(gè)能夠動(dòng)態(tài)繪制多條曲線的折線圖表。通過(guò)定時(shí)器控制數(shù)據(jù)點(diǎn)的逐步繪制,并結(jié)合坐標(biāo)軸的動(dòng)態(tài)更新,使得該圖表在繪圖過(guò)程中能夠自動(dòng)適應(yīng)數(shù)據(jù)的變化。這種方式適用于需要實(shí)時(shí)顯示數(shù)據(jù)變化的場(chǎng)景,如傳感器數(shù)據(jù)的實(shí)時(shí)監(jiān)控或動(dòng)態(tài)性能分析等。
到此這篇關(guān)于使用Qt實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)動(dòng)態(tài)繪制的折線圖示例的文章就介紹到這了,更多相關(guān)Qt動(dòng)態(tài)折線圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++使用opencv調(diào)用級(jí)聯(lián)分類(lèi)器來(lái)識(shí)別目標(biāo)物體的詳細(xì)流程
所謂級(jí)聯(lián)分類(lèi)器其實(shí)就是把分類(lèi)器按照一定的順序聯(lián)合到一起,下面這篇文章主要給大家介紹了關(guān)于C++使用opencv調(diào)用級(jí)聯(lián)分類(lèi)器來(lái)識(shí)別目標(biāo)物體的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05詳解C/C++中const關(guān)鍵字的用法及其與宏常量的比較
簡(jiǎn)單的說(shuō)const關(guān)鍵字修飾的變量具有常屬性,也就是說(shuō)它所修飾的變量不能被修改,下文給大家介紹C/C++中const關(guān)鍵字的用法及其與宏常量的比較,需要的朋友可以參考下2017-07-07C語(yǔ)言中access/_access函數(shù)的使用實(shí)例詳解
本文通過(guò)實(shí)例代碼給大家介紹了C語(yǔ)言中access/_access函數(shù)的使用,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09C語(yǔ)言實(shí)現(xiàn)任意進(jìn)制轉(zhuǎn)換器
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)任意進(jìn)制轉(zhuǎn)換器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01Qt編寫(xiě)地圖實(shí)現(xiàn)省市區(qū)域圖的示例代碼
本文主要介紹了Qt編寫(xiě)地圖實(shí)現(xiàn)省市區(qū)域圖的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12