Qt Charts - 實時曲線


1、添加坐標軸

先在工程中添加QChart、QChartView,代碼如下:

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    chart = new QChart();
    ChartView = new QChartView(this);
    ChartView->setChart(chart);
    ui->verticalLayout->addWidget(ChartView);
}

然后定義兩個坐標軸,一個用作X軸,一個用作Y軸,
添加頭文件:

#include <QtCharts/QValueAxis>

創建兩個QValueAxis:

QValueAxis *axisX;
    QValueAxis *axisY;

在構造函數中,對兩個坐標軸進行實例化,把X軸范圍設置為0-10並放置在坐標系的底部,Y軸范圍設置為0-10並放置在坐標系的左邊,並且添加到QChart中,如下:

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    chart = new QChart();

    axisX = new QValueAxis();
    axisY = new QValueAxis();

    chart->addAxis(axisX,Qt::AlignBottom);
    chart->addAxis(axisY,Qt::AlignLeft);

    axisX->setTickCount(5);
    axisX->setRange(0, 10);
    axisY->setRange(0, 10);

    ChartView = new QChartView(this);
    ChartView->setChart(chart);
    ui->verticalLayout->addWidget(ChartView);
}

編譯運行,結果如下:

 

 

 

從上圖可以看出,成功創建了一個笛卡爾坐標系。

2、使用定時器動態添加數據

這里嘗試下使用曲線圖,創建一個曲線序列,

  • 添加頭文件
#include <QtCharts/QSplineSeries>
  • 在類聲明中添加:
 QSplineSeries *series;
  • 在構造函數中對series進行實例化,並跟之前創建的坐標軸關聯起來:
series = new QSplineSeries(this);
  series->attachAxis(axisX);
  series->attachAxis(axisY);

然后添加定時器:

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    // .....
    QTimer timer;
    connect(&timer, &QTimer::timeout, this, &Chart::Timeout_handler);
    timer.setInterval(1000);
}

void Dialog::Timeout_handler()
{
    // 定時器執行代碼……
}

首先定義一個整形變量x_index,初始化為0,用來給series序列中的x賦值,定時器每觸發一個事件,使用隨機數生成函數生成的值給series序列中的y賦值,然后x_index的值加一,主要代碼如下:

void Dialog::Timeout_handler()
{
    QDateTime dt;
    QString current_dt = dt.currentDateTime().toString("yyyy:MM:dd:hh:mm:ss:zzz");
    qsrand(dt.currentDateTime().toTime_t());
    int y = qrand() % 10;
    series->append(x_index,y);
    x_index ++;
    qDebug()<<"x_index:"<<x_index;
}

運行結果如下:

 

 

 

 

從上圖中可以看到曲線是動起來了,可是當x_index大於10的時候,曲線就沒有動了,也就是時序列series第10個及后面數據都沒有顯示出來,

3、實現實時曲線

因為之前X軸范圍為0-10,能顯示的數據也就只有x值在0-10范圍內,超過10的就無法顯示,那如果要顯示實時更新的數據,該怎么操作呢?

1. 一個方法是當序列series中的數據增加時,X軸范圍也增加,代碼如下:

void Dialog::Timeout_handler()
{
    QDateTime dt;
    QString current_dt = dt.currentDateTime().toString("yyyy:MM:dd:hh:mm:ss:zzz");
    qsrand(dt.currentDateTime().toTime_t());
    int y = qrand() % 10;
    series->append(x_index,y);

    if(x_index > 10)
        axisX->setRange(0, x_index);
    x_index ++;
}

當 x_index 超過 10 后,每增加一個,就把x軸顯示范圍設置為 0-x_inxex,顯示效果如下:

 

 

 

 

2. 還是改變x軸的,不過,可顯示區域是固定的

void Dialog::Timeout_handler()
{
    QDateTime dt;
    QString current_dt = dt.currentDateTime().toString("yyyy:MM:dd:hh:mm:ss:zzz");
    qsrand(dt.currentDateTime().toTime_t());
    int y = qrand() % 10;
    series->append(x_index,y);

    if(x_index > 10)
        axisX->setRange(x_index-10, x_index);
    x_index ++;
}

3. 使用scroll方法

代碼如下:

void Dialog::Timeout_handler(){    
  QDateTime dt;    
  QString current_dt = dt.currentDateTime().toString("yyyy:MM:dd:hh:mm:ss:zzz");    
  qsrand(dt.currentDateTime().toTime_t());    
  int y = qrand() % 10;    
  series->append(x_index,y);    
  qreal x = chart->plotArea().width() / 10;    
  if(x_index > 10)        
    chart->scroll(x,0);    
  x_index ++;
}

 

4. 更新全部serial

這種方法是保持序列series的x軸的值不變,都是0-10,改變的是0-10對應的y軸的值,首先定義一個list用來保存獲取到的Y軸的值:

QList<int> y_list;
void Dialog::Timeout_handler()
{
    QDateTime dt;
    QString current_dt = dt.currentDateTime().toString("yyyy:MM:dd:hh:mm:ss:zzz");
    qsrand(dt.currentDateTime().toTime_t());
    int y = qrand() % 10;
    y_list.append(y);
    if(y_list.length()>11)
        y_list.removeFirst();
    QList<QPointF> points;
    points.clear();
    for(int i=0;i<y_list.length();i++)
    {

        points.append(QPointF(i,y_list.at(i)));
    }
    series->replace(points);
}

效果如下:

 

上圖中可以看到,圖標中的曲線一直在變化,可是X軸的范圍保持在0-10,

本文來自博客園,作者:哈拎,原文鏈接:https://www.cnblogs.com/halin/p/14745338.html

 


免責聲明!

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



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