QCustomPlot使用心得四:動態曲線和繪圖效率測試


轉自: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添加到相應路徑,有興趣的試一下吧,博主就沒試了。

 

四、下載

測試例程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM