1. 程式人生 > >QtChart——簡單的動態波形圖

QtChart——簡單的動態波形圖

眾所周知Qt 5.7過後Qt添加了官方的Chart庫,終於可以用官方的庫替代QWT和QCustomerPlot。本文只是簡單的融合了幾個Qt官方例子。程式執行圖如下:
這裡寫圖片描述

功能點

其實大家來看部落格,就是來看有啥功能,能ctrl + C加ctrl + V到自己專案裡的,至於原理,有興趣的同學可以自己去看看Qt原始碼,所以這裡就主要講一下本例有什麼功能:

  1. 資料動態更新。例子裡是定時器,定時更新一個正弦波。
  2. 放大縮小。通過滑鼠滾輪實現影象放大縮小功能。
  3. 比例復原。當你不小心把影象弄丟了,沒關係,點選一下滑鼠右鍵就行了。
  4. 座標顯示。滑鼠懸停到資料線條上就會顯示,XY座標的值。
  5. 影象拖拽。不能拖拽那有啥意思?

接下來就簡單講解一下每個功能點的簡單實現,基礎知識我就不講了,因為我也不知道,寫程式碼就是一個搬運的過程。

資料動態更新

說道資料動態更新,但凡用過QWT和QCustomerPlot的同學都知道,這樣做:

QVector<QPointF> data;

if (data.size() >
max) { data.pop_back(); data.push_front(point); } else { data.push_front(point); }

每次只需要把最後的資料彈出去,然後新增新的資料就OK了,但是QChart這個地方有點意思,到替換原來資料的時候,前面資料和後面資料就連一起了,一條好好的正弦波多了一條線,肯定不爽啊。然後就看了Qt的Example,在audio那,就是音訊資料採集那,但凡做過AD資料採集的同學應該都懂,然後我當然就把那的程式碼化為己有了:

void MainWidget::updateData()
{
    int i;
    QVector
<QPointF> oldData = series->pointsVector(); QVector<QPointF> data; if (oldData.size() < 97) { data = series->pointsVector(); } else { /* 新增之前老的資料到新的vector中,不復制最前的資料,即每次替換前面的資料 * 由於這裡每次只新增1個數據,所以為1,使用時根據實際情況修改 */ for (i = 1; i < oldData.size(); ++i) { data.append(QPointF(i - 1 , oldData.at(i).y())); } } qint64 size = data.size(); /* 這裡表示插入新的資料,因為每次只插入1個,這裡為i < 1, * 但為了後面方便插入多個數據,先這樣寫 */ for(i = 0; i < 1; ++i){ data.append(QPointF(i + size, 10 * sin(M_PI * count * 4 / 180))); } series->replace(data); count++; }

清楚明瞭,每次都需要copy一次資料,不過這種方法效率不知道怎麼樣,普通的採集還好,我之前公司的專案,收資料是按us級來搞的,所以之前用QCustomerPlot效果也不太好,一次replot()就是3個ms(畢竟QCustomerPlot的底層也是copy了一次資料= =!),那我得漏多少條資料。。。

放大縮小

這個就比較好搞,一個滑鼠滾輪事件:

void MainWidget::wheelEvent(QWheelEvent *event)
{
    if (event->delta() > 0) {
        chart->zoom(1.1);
    } else {
        chart->zoom(10.0/11);
    }

    QWidget::wheelEvent(event);
}

比例自己定,這裡我的是比例是10%。

比例復原

其實就呼叫了一個zoomReset()函式:

void ChartView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() & Qt::LeftButton) {
        isClicking = true;
    } else if (event->button() & Qt::RightButton) {
        chart()->zoomReset();
    }

    QChartView::mousePressEvent(event);
}

座標顯示

改自官方Example的Callout,其實我就改了一下命名,因為有程式碼潔癖,不習慣匈牙利命名法,C++喜歡用駝峰,C語言還是K&C,然後內容沒改,但願不會被查水錶,具體程式碼就不貼了,下面發整個工程的程式碼連結。

影象拖拽

就是一個mousePressEvent和mouseMoveEvent事件,滑鼠按下了把標誌位變為true,然後在滑鼠Move的時候檢測標誌位是否為true,如果是就根據座標計算scroll值:

void ChartView::mouseMoveEvent(QMouseEvent *event)
{
    int x, y;

    if (isClicking) {
        if (xOld == 0 && yOld == 0) {

        } else {
            x = event->x() - xOld;
            y = event->y() - yOld;
            chart()->scroll(-x, y);
        }

        xOld = event->x();
        yOld = event->y();

        return;
    }

    QChartView::mouseMoveEvent(event);
}

程式碼連結:
https://github.com/DragonPang/QtChart