轉自:https://blog.csdn.net/yxy244/article/details/100099876
一、先看官方例子
https://www.qcustomplot.com/index.php/demos/realtimedatademo:
頭文件添加:
1 QTimer dataTimer; 2 private slots: 3 void realtimeDataSlot();
構造函數里:
QCustomPlot* customPlot = ui->customPlot_7; customPlot->addGraph(); customPlot->graph(0)->setPen(QPen(QColor(40, 110, 255)));//曲線1藍色 customPlot->addGraph(); customPlot->graph(1)->setPen(QPen(QColor(255, 110, 40)));//曲線2紅色 //坐標軸使用時間刻度 QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime); timeTicker->setTimeFormat("%h:%m:%s"); customPlot->xAxis->setTicker(timeTicker); //四邊安上坐標軸 customPlot->axisRect()->setupFullAxesBox(); //設置y軸范圍 customPlot->yAxis->setRange(-1.2, 1.2); // 使上下軸、左右軸范圍同步 connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange))); connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange))); //定時器連接槽函數realtimeDataSlot connect(&dataTimer, SIGNAL(timeout()), this, SLOT(realtimeDataSlot())); dataTimer.start(0); // 間隔時間 0ms表示盡可能快的觸發
realtimeDataSlot函數:
1 2 void MainWindow::realtimeDataSlot() 3 { 4 QCustomPlot* customPlot = ui->customPlot_7; 5 static QTime time(QTime::currentTime()); 6 7 double key = time.elapsed()/1000.0; // 開始到現在的時間,單位秒 8 static double lastPointKey = 0; 9 if (key-lastPointKey > 0.002) // 大約2ms添加一次數據 10 { 11 // 添加數據到graph 12 customPlot->graph(0)->addData(key, qSin(key)+qrand()/(double)RAND_MAX*1*qSin(key/0.3843)); 13 customPlot->graph(1)->addData(key, qCos(key)+qrand()/(double)RAND_MAX*0.5*qSin(key/0.4364)); 14 //記錄當前時刻 15 lastPointKey = key; 16 } 17 // 曲線能動起來的關鍵在這里,設定x軸范圍為最近8個時刻 18 customPlot->xAxis->setRange(key, 8, Qt::AlignRight); 19 //繪圖 20 customPlot->replot(); 21 //計算幀數 22 static double lastFpsKey; 23 static int frameCount; 24 ++frameCount; 25 if (key-lastFpsKey > 2) // 每2秒求一次平均值 26 { 27 //狀態欄顯示幀數和數據總數 28 ui->statusBar->showMessage( 29 QString("%1 FPS, Total Data points: %2") 30 .arg(frameCount/(key-lastFpsKey), 0, 'f', 0) 31 .arg(customPlot->graph(0)->data()->size()+customPlot->graph(1)->data()->size()) 32 , 0); 33 lastFpsKey = key; 34 frameCount = 0; 35 } 36 }
滾動曲線的關鍵是改變軸范圍,調用
void QCPAxis::setRange (double position, double size, Qt::AlignmentFlag alignment )
第一個參數是軸所在位置,size定義軸范圍的數據點個數,第三個是軸的對齊方式,可以是Qt::AlignLeft、Qt::AlignRight或Qt::AlignCenter。
在這里每次添加數據后調用一次setRange(key, 8, Qt::AlignRight),最新的數據的key值當做軸顯示在右邊,原來最左邊的數據被擠了出去,看起來曲線整體向左移了,因為x軸設置為時間刻度,所以顯示的范圍是8秒。
二、繪圖性能測試
官網的例程有個不好的地方,曲線刷新太頻繁了,現實中顯示器刷新率一般60Hz,而電影一般才24幀,所有沒必要每添加一個數據就刷新一次,可以采用定時刷新,控制幀數在60幀內就行了,這里做個測試,看看QCustomPlot的性能如何。
博主的電腦CPU是渣渣的I5 6200U,直接先看測試結果:
(1)1條曲線性能很好,每幀10萬點還能保持60fps,1百萬的時候有50多的fps
(2)5條曲線每幀50萬點數據大概有四五十fps
(3)20條曲線的時候fps下降得厲害,每幀10多萬點就40的fps,加到每幀200萬點就只有26fps了
(4)窗口尺寸對性能影響巨大,繪制5條曲線,在小尺寸下能保持60fps,但是拉大后fps下降得厲害
結論:
繪制動態曲線,在曲線數很少的情況下效率很高,即使百萬級也不卡頓,曲線數多了會影響性能;窗口尺寸對性能影響很大,尺寸越大性能下降得厲害。
添加數據和重繪分開,使用定時重繪,重繪時調用customPlot->replot(QCustomPlot::rpQueuedReplot),而不是replot(),這樣就可以避免多次重復的繪制。
上述測試代碼:
界面兩個spinbox,兩個button
頭文件
1 QTimer rePlotTimer; 2 QTimer dataTimer; 3 bool m_start; 4 int m_countGraph; 5 private slots: 6 void timeToAddData(); 7 void timeToRePlot(); 8 void on_pushButton_clicked(); 9 void on_btn1_clicked();
開始按鈕槽函數:
1 void MainWindow::on_btn_start_clicked() 2 { 3 QCustomPlot* customPlot = ui->customPlot_7; 4 5 if(!m_start) 6 { 7 customPlot->clearGraphs();//清除所有graph 8 m_countGraph = ui->spinBox1->value(); 9 QPen pen; 10 pen.setWidth(1); 11 //添加曲線 12 for(int i=0;i<m_countGraph;i++) 13 { 14 customPlot->addGraph(); 15 //顏色隨機 16 pen.setColor(QColor(qrand()%150+100,qrand()%150+100,qrand()%150+100)); 17 customPlot->graph(i)->setPen(pen);// 18 } 19 //設置y軸范圍 20 customPlot->yAxis->setRange(-1, m_countGraph*2); 21 //設置x軸范圍 22 int size = ui->spinBox2->value(); 23 customPlot->xAxis->setRange(0, size, Qt::AlignRight); 24 //定時添加和刷新數據 25 rePlotTimer.start(16); // 間隔16ms刷新一次 26 dataTimer.start(5); // 間隔時間5ms添加一次數據 27 m_start = true; 28 ui->btn_start->setText("停止"); 29 } 30 else 31 { 32 rePlotTimer.stop(); // 停止重繪 33 dataTimer.stop(); // 停止添加數據 34 m_start = false; 35 ui->btn_start->setText("開始"); 36 } 37 }
添加數據按鈕槽函數:
void MainWindow::on_btn_adddata_clicked() { QCustomPlot* customPlot = ui->customPlot_7; //x軸范圍點數 int size = ui->spinBox2->value(); for(int i=0;i<customPlot->graphCount();i++)//添加x軸范圍的點數,使波形占滿畫面 { for(int j=0;j<size;j++) { customPlot->graph(i)->addData(customPlot->graph(i)->dataCount(),qrand()/(double)RAND_MAX + i*2); } } }
定時添加數據:
void MainWindow::timeToAddData() { QCustomPlot* customPlot = ui->customPlot_7; QTime time= QTime::currentTime(); qsrand(time.msec()+time.second()*1000);//種子 for(int i=0;i<customPlot->graphCount();i++) { for(int j=0;j<10;j++)//每次添加10個數據 { customPlot->graph(i)->addData(customPlot->graph(i)->dataCount(),qrand()/(double)RAND_MAX + i*2); } } }
定時重繪:
1 void MainWindow::timeToRePlot() 2 { 3 static QTime time(QTime::currentTime()); 4 double key = time.elapsed()/1000.0; // time elapsed since start of demo, in seconds 5 6 QCustomPlot* customPlot = ui->customPlot_7; 7 int size = ui->spinBox2->value(); 8 9 customPlot->xAxis->setRange(customPlot->graph(0)->dataCount(), size, Qt::AlignRight); 10 //重繪 11 customPlot->replot(QCustomPlot::rpQueuedReplot); 12 //customPlot->replot(); 13 static double lastFpsKey; 14 static int frameCount; 15 ++frameCount; 16 if (key-lastFpsKey > 1) // 每1s求一次值 17 { 18 int displaySize = ui->spinBox2->value();//單條顯示點數 19 int datasize = customPlot->graph(0)->data()->size();//單條數據總數 20 int graphCount= m_countGraph;//曲線條數 21 long displaytotal=displaySize*graphCount;//顯示總數 22 long datatotal=datasize*graphCount;//數據總數 23 QString str_displaytotal; 24 QString str_datatotal; 25 //顯示的總數不會超過實際點數 26 if(displaytotal > datatotal) 27 { 28 displaytotal = datatotal; 29 } 30 //顯示點數加單位更直觀 31 if(displaytotal>=1e6)//百萬級 32 { 33 str_displaytotal = QString("%1百萬").arg(displaytotal/1000000.0,0,'f',2); 34 } 35 else if(displaytotal>=1e4)//萬級 36 { 37 str_displaytotal = QString("%1萬").arg(displaytotal/10000.0,0,'f',2); 38 } 39 else 40 { 41 str_displaytotal=QString("%1").arg(displaytotal); 42 } 43 //總數加單位更直觀 44 if(datatotal>=1e6)//百萬級 45 { 46 str_datatotal = QString("%1百萬").arg(datatotal/1000000.0,0,'f',2); 47 } 48 else if(datatotal>=1e4)//萬級 49 { 50 str_datatotal = QString("%1萬").arg(datatotal/10000.0,0,'f',2); 51 } 52 else 53 { 54 str_datatotal=QString("%1").arg(datatotal); 55 } 56 ui->statusBar->showMessage( 57 QString("FPS:%1,顯示總數:%2*%3=%4,數據總數:%5*%6=%7") 58 .arg(frameCount/(key-lastFpsKey), 0, 'f', 0) 59 .arg(displaySize) 60 .arg(graphCount) 61 .arg(str_displaytotal) 62 .arg(datasize) 63 .arg(graphCount) 64 .arg(str_datatotal) 65 , 0); 66 lastFpsKey = key; 67 frameCount = 0; 68 } 69 }
三、使能opengl
QCustomPlot有opengl功能,想試下GPU加速繪圖的效果。
按照提示添加 DEFINES += QCUSTOMPLOT_USE_OPENGL到pro文件,
代碼里開啟:customPlot->setOpenGl(true);
但是編譯報錯誤
網友提示還要.pro里加入
1 win32:LIBS += -lOpengl32\ 2 -lglu32 \ 3 -lglut
調試輸出顯示是否開啟了opengl
qDebug()<<"opengl:"<<customPlot->openGl();
glut庫要下載的,dll和lib添加到相應路徑,有興趣的試一下吧,博主就沒試了。