QML使用QCustomPlot

创建一个类,继承QQuickPaintedItem

示例,创建一个 TimeDomainPlot 类

TimeDomainPlot.h

#ifndef TIMEDOMAINPLOT_H
#define TIMEDOMAINPLOT_H

#include "qcustomplot.h"
#include <QRect>
#include <QQuickPaintedItem>

class TimeDomainPlot: public QQuickPaintedItem
{

public:
    explicit TimeDomainPlot(QQuickItem* parent = nullptr);
    ~TimeDomainPlot();

    const static int DATA_SIZE;
    const static double XAXIS_RANGE_START;
    const static double XAXIS_RANGE_END;

    virtual void paint(QPainter *painter);

    void setVoltageGraphData(const QVector<double> &keys, const QVector<double> &values);
    void setCurrentGraphData(const QVector<double> &keys, const QVector<double> &values);
    void setVoltageRange(double min, double max);
    void setCurrentRange(double min, double max);
    void replot();

private:
    QCustomPlot *_customPlot;
    QCPGraph* _voltageGraph;
    QCPGraph* _currentGraph;
};

#endif // TIMEDOMAINPLOT_H

TimeDomainPlot.cpp

#include "TimeDomainPlot.h"
#include <QQuickItem>

const int TimeDomainPlot::DATA_SIZE = 512;
const double TimeDomainPlot::XAXIS_RANGE_START = 0;
const double TimeDomainPlot::XAXIS_RANGE_END = 400;

TimeDomainPlot::TimeDomainPlot(QQuickItem *parent): QQuickPaintedItem(parent)
{
    _customPlot = new QCustomPlot();
    _voltageGraph = _customPlot->addGraph();
    _currentGraph = _customPlot->addGraph(_customPlot->xAxis, _customPlot->yAxis2);
    //设置颜色
    _voltageGraph->setPen(QPen(Qt::red));
    _currentGraph->setPen(QPen(Qt::blue));
    //设置Y轴范围
    _customPlot->yAxis->setNumberFormat("gbc");/* g 灵活的格式,b 漂亮的指数形式,c 乘号改成 x */
    _customPlot->yAxis->setNumberPrecision(1);/* 精度 1 */
    _customPlot->xAxis->setRange(XAXIS_RANGE_START, XAXIS_RANGE_END);
    _customPlot->yAxis2->setNumberFormat("gbc");/* g 灵活的格式,b 漂亮的指数形式,c 乘号改成 x */
    _customPlot->yAxis2->setNumberPrecision(1);/* 精度 1 */
    _customPlot->yAxis2->setVisible(true);
    //x轴名字
    _customPlot->xAxis->setLabel("时间 / ms");
    //Y轴名字
    _customPlot->yAxis->setLabel("电压 / V");
    _customPlot->yAxis->setTickLabelColor("red");
    _customPlot->yAxis->setLabelColor("red");
    _customPlot->yAxis2->setLabel("电流 / mA");
    _customPlot->yAxis2->setTickLabelColor("blue");
    _customPlot->yAxis2->setLabelColor("blue");
}

TimeDomainPlot::~TimeDomainPlot()
{
    delete _customPlot;
}

void TimeDomainPlot::paint(QPainter *painter)
{
    _customPlot->setGeometry(0,0,this->width(),this->height());
    painter->drawPixmap(0,0,this->width(),this->height(), _customPlot->toPixmap());
}

void TimeDomainPlot::setVoltageGraphData(const QVector<double> &keys, const QVector<double> &values)
{
    _voltageGraph->setData(keys, values);
}

void TimeDomainPlot::setCurrentGraphData(const QVector<double> &keys, const QVector<double> &values)
{
    _currentGraph->setData(keys, values);
}

void TimeDomainPlot::setVoltageRange(double min, double max)
{
    _customPlot->yAxis->setRange(min, max);
}

void TimeDomainPlot::setCurrentRange(double min, double max)
{
    _customPlot->yAxis2->setRange(min, max);
}

void TimeDomainPlot::replot()
{
    update(QRect(x(),y(),width(), height()));
}

在main.cpp进行注册

main.cpp:

#include <QApplication>
#include <QQmlEngine>
#include <QQmlContext>
#include "TimeDomainPlot.h"
//#include "DataSource.h"
#include "QQuickView"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QQuickView viewer;

    qmlRegisterType<TimeDomainPlot>("myqml",1,0,"TimeDomainPlot");

    QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QWindow::close);

    viewer.setTitle(QStringLiteral("test"));

    // DataSource dataSource(&viewer);
    // viewer.rootContext()->setContextProperty("dataSource", &dataSource);

    viewer.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
    viewer.setResizeMode(QQuickView::SizeRootObjectToView);
    viewer.show();

    return app.exec();
}

在 main.qml 创建 TimeDomainPlot 对象

main.qml

import QtQuick 2.9
import myqml 1.0

Item {
    id: root
    width: 1024
    height: 600
    visible: true

	TimeDomainPlot {
        id: timeDomainChart
        x:0;y:0;width: root.width;height: root.height
    }
}

此时编译运行即可看到图表添加并渲染完成。

添加数据更新方法

  1. 创建 DataSource 类,继承QObject

DataSource.h

#ifndef DATASOURCE_H
#define DATASOURCE_H

#include <QtCore/QObject>
#include "TimeDomainPlot.h"

QT_BEGIN_NAMESPACE
class QQuickView;
QT_END_NAMESPACE


class DataSource : public QObject
{
    Q_OBJECT
public:
    static const int DATA_SIZE;

public:
    explicit DataSource(QQuickView *appViewer, QObject *parent = 0);
    ~DataSource();

Q_SIGNALS:

public slots:
    void generateData();
    void updateTimeDomain(TimeDomainPlot *plot);

private:
    QQuickView *m_appViewer;
    QVector<double> m_timeDomainX;
    QVector<double> m_timeDomainV;
    QVector<double> m_timeDomainI;
};

#endif // DATASOURCE_H

DataSource.cpp

#include "DataSource.h"
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
#include <QtCore/QDebug>
#include <QtCore/QRandomGenerator>
#include <QtCore/QtMath>
#include <QDebug>

Q_DECLARE_METATYPE(TimeDomainPlot *)

const int DataSource::DATA_SIZE = TimeDomainPlot::DATA_SIZE;

DataSource::DataSource(QQuickView *appViewer, QObject *parent) :
    QObject(parent),
    m_appViewer(appViewer)
{
    qRegisterMetaType<TimeDomainPlot *>();
    m_timeDomainX.resize(DATA_SIZE);
    m_timeDomainV.resize(DATA_SIZE);
    m_timeDomainI.resize(DATA_SIZE);
}

DataSource::~DataSource()
{
}

void DataSource::updateTimeDomain(TimeDomainPlot *plot)
{
    if (plot) {

        QVector<double> &pointX = m_timeDomainX;
        QVector<double> &pointY = m_timeDomainV;
        auto min = pointY[0];
        auto max = pointY[0];
        for (auto point : pointY)
        {
            min = point < min ? point : min;
            max = point > max ? point : max;
        }
        plot->setVoltageGraphData(pointX,pointY);
        plot->setVoltageRange(2 * min - max, max);


        pointY = m_timeDomainI;
        min = pointY[0];
        max = pointY[0];
        for (auto point : pointY)
        {
            min = point < min ? point : min;
            max = point > max ? point : max;
        }
        plot->setCurrentGraphData(pointX,pointY);
        plot->setCurrentRange(min, 2 * max - min);
        plot->replot();
    }
}

void DataSource::generateData()
{
    for (int j(0); j < DATA_SIZE; j++) {
        double x(0);
        double y(0);
        double y2(0);
        y = qSin(M_PI / 32 * j) + 0.5 + QRandomGenerator::global()->generateDouble();
        y2 = qSin(M_PI / 32 * (j + 5)) + 0.5 + QRandomGenerator::global()->generateDouble();
        x = (j * 400) / (DATA_SIZE - 1);
        m_timeDomainX[j] = x;
        m_timeDomainV[j] = y;
        m_timeDomainI[j] = y2;
    }
}


  1. 在 main.cpp 中创建 DataSource 对象,并注册到 QML对象的上下文。(打开上面main.cpp中注释的部分即可)
DataSource dataSource(&viewer);
viewer.rootContext()->setContextProperty("dataSource", &dataSource);
  1. 在main.qml中创建个Timer 定时更新数据
Timer {
            id: refreshTimer
            interval: 1 / 1 * 1000 // 1 Hz
            running: root.running
            repeat: true
            onTriggered: {
                dataSource.generateData()
                dataSource.updateTimeDomain(timeDomainChart)
            }
        }
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值