您当前的位置:首页 > IT编程 > python
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:Qt自定义Plot实现曲线绘制的详细过程

51自学网 2022-02-21 10:49:43
  python
这篇教程Qt自定义Plot实现曲线绘制的详细过程写得很实用,希望能帮到您。

简介

实现了qt绘制曲线功能,包含arm触摸屏多点触控缩放(只支持两点),实时曲线绘制,数据点根据绘制宽度优化,跟踪点数据获取,双坐标等功能

演示

请添加图片描述

请添加图片描述

代码

头文件 plot.h

/* * 作者:老人与海 * 博客:https://blog.csdn.net/qq_41340733 * 代码不保证稳定性,请勿用于商业用途 */#ifndef PLOT_H#define PLOT_H#include <QWidget>#include <QTimer>#include <QList>#include <QWheelEvent>#include <QMouseEvent>#include "plotdata.h"typedef struct _RangeVal{    double Beg;    double End;    double offSet;    bool IsOffSet;    _RangeVal()    {        Beg=0;        End=0;        offSet=0;        IsOffSet=false;    }}_RangeVal;//鼠标跟中点class Tracking{public:    Tracking()    {        m_IsDraw=false;        m_IsMove=false;        m_IsInit=false;        m_First=false;        m_radius=25;        m_PointCenter=QPoint(0,0);    }    ~Tracking(){}    bool getIsRange(QPoint point)    {        if(point.x()>(m_PointCenter.x()-m_radius)&&                point.x()<(m_PointCenter.x()+m_radius)&&                point.y()>(m_PointCenter.y()-m_radius)&&                point.y()<(m_PointCenter.y()+m_radius))        {            return true;        }else{            return false;        }    }public:    bool m_IsDraw;    bool m_IsMove;//鼠标焦点    bool m_IsInit;    bool m_First;    int m_radius;    QPoint m_PointCenter;//绘制圆心};/** * @brief The CoorAxis class * 类名:CoorAxis * 功能:坐标轴部件,用来绘制XY坐标轴,使用时必须用Plot的ticker类进行初始化,否则无法正常绘制坐标 */class CoorAxis : public QWidget{    Q_OBJECTpublic:    explicit CoorAxis(QWidget *parent = nullptr,Ticker *ticker= nullptr);    virtual ~CoorAxis();    Ticker *ticker(){ return m_Ticker; }    void mouseMove(QMouseEvent *event);signals:    void sig_UpdateUI();public slots:    void slots_sendCoorWheel(QWheelEvent *event);    void slots_sendCoorMouse(QMouseEvent *event,QPoint point,bool IsFirst=false);protected:   void paintEvent(QPaintEvent *event);   void drawTickerX(QPainter *painter);//绘制X轴   void drawTickerY_L(QPainter *painter);//绘制左边Y轴   void drawTickerY_R(QPainter *painter);//绘制右边Y轴   void wheelEvent(QWheelEvent *event);//滚轮事件,缩放曲线图像   void mousePressEvent(QMouseEvent *event);//按下事件,记录坐标和按下标志   void mouseReleaseEvent(QMouseEvent *event);//抬起事件,取消按下标志   void mouseMoveEvent(QMouseEvent *event);//鼠标移动事件,移动曲线protected:   Ticker *m_Ticker;   int m_LastLength;   int m_margin;   bool IsPress=false;   QPoint m_FirstPoint;};class Plot : public QWidget{    Q_OBJECTpublic:    explicit Plot(QWidget *parent=nullptr);    virtual ~Plot();    void ValueInit();    Ticker *tickerX();    Ticker *tickerL();    Ticker *tickerR();    void addGraph();    void GraphClear(){ m_XyGraph.clear(); }    int getGraphCount(){ return m_XyGraph.count(); }    _XYList *Graph(int index);    QList<_XYList> &GraphGroup(){ return m_XyGraph; }    void setTrackVisibel(bool isVisbel){ m_Tracking.m_IsDraw=isVisbel; }    bool getTrackVisibel(){ return m_Tracking.m_IsDraw; }    void setIsDrawPath(bool value){ m_IsDrawPath=value; }    bool getIsDrawPath(){ return m_IsDrawPath; }    void coordToPixel(_COORDINATEVALUE *Value,_TICKERTYPE Type);    void coordToPixel(double &key,double &value,_TICKERTYPE Type);    void PixelToCoorKey(double &key,_TICKERTYPE Type);    void PixelToCoorValue(double &value,_TICKERTYPE Type);    void PixelToCoord(QPointF &pointf,_TICKERTYPE Type);    void getOptimizedLineData(QVector<QPointF> *lineData,int index);    void calculateTrackValue(QPoint Point);    void setBackgroundColor(QColor color){ m_BackgroundColor=color; }    QColor getBackgroundColor(){ return m_BackgroundColor; }signals:    void sig_sendCoorWheel(QWheelEvent *event);    void sig_sendCoorMouse(QMouseEvent *event,QPoint point,bool IsFirst=false);    void sig_UpdateUI();    void sig_UpdateTrack();//刷新跟踪点数据public slots:protected:   void paintEvent(QPaintEvent *event);   void drawGrid(QPainter *painter);//绘制网格   void drawPath(QPainter *painter);//绘制曲线   void drawCursor(QPainter *painter);//绘制跟踪点   void drawTickerX(QPainter *painter);//绘制X轴   void drawTickerY_L(QPainter *painter);//绘制左边Y轴   void drawTickerY_R(QPainter *painter);//绘制右边Y轴   void wheelEvent(QWheelEvent *event);//滚轮事件,缩放曲线图像   void mousePressEvent(QMouseEvent *event);//按下事件,记录坐标和按下标志   void mouseReleaseEvent(QMouseEvent *event);//抬起事件,取消按下标志   void mouseMoveEvent(QMouseEvent *event);//鼠标移动事件,移动曲线   void showEvent(QShowEvent *event);//显示事件   bool event(QEvent *event);//事件,实现多点触控功能,目前只对两个触控点做了处理public:   QPixmap m_PixMapCursor;//跟踪点绘制图像缓冲   Tracking m_Tracking;protected:   Ticker *m_TickerX;   Ticker *m_TickerL;   Ticker *m_TickerR;   bool IsPress=false;   bool m_IsTouch=false;   QPoint m_ClickedPoint;   qreal m_scaleFactorX=0.0;   qreal m_scaleFactorY=0.0;   QList<_XYList> m_XyGraph;   QColor m_BackgroundColor;   bool m_IsDrawPath;//是否绘制曲线,在多线程添加数据的时候调用,添加数据时禁止绘制曲线private:   friend class Ticker;};class CurveWid : public QWidget{    Q_OBJECTpublic:    explicit CurveWid(QWidget *parent = nullptr);    void DataInit();    void reUpdate();    void reUpdateAll();signals:public slots:    void slots_UpdateUI();    void slots_TimeOut();protected:    void paintEvent(QPaintEvent *event);public:    CoorAxis *m_AxisX;    CoorAxis *m_AxisL;    CoorAxis *m_AxisR;    Plot *m_Plot;    QTimer *m_Timer;};#endif // PLOT_H

头文件plotdata.h

/* * 作者:老人与海  * 博客:https://blog.csdn.net/qq_41340733 * 代码不保证稳定性,请勿用于商业用途 */#ifndef PLOTDATA_H#define PLOTDATA_H#include <QObject>#include <QVector>#include <QColor>class CoorAxis;//_COORDINATEVALUE单个数据点结构体typedef struct _COORDINATEVALUE{    double Key;    double Value;    _COORDINATEVALUE()    {        Key=0;        Value=0;    }}_COORDINATEVALUE;//坐标轴绘制的文本类型,包括时间毫秒,时间秒,数值typedef enum _TEXT_TYPE{    _TimeMs,    _TimeS,    CountVal}_TEXT_TYPE;//坐标轴类型,XAxis表示X轴,YAxis_L表示左边的Y轴,YAxis_R表示右边的Y轴typedef enum _TICKERTYPE{    XAxis=0,    YAxis_L=1,    YAxis_R=2}_TICKERTYPE;//坐标缩放前的坐标值,_begVal坐标起始值,_endVal坐标结束值,_siteVal坐标中点,//多点触控的时候先记录坐标的原始值,然后根据手势距离对原始进行缩放typedef struct _Scale{    double _begVal=0.0;    double _endVal=0.0;    double _siteVal=0.0;}_Scale;/** * @brief The _XYList class * 功能:单条曲线的数据结构类型,包括坐标轴类型,曲线颜色, * 最多可绘制的曲线点数,等功能等; */class _XYList{public:    explicit _XYList();    virtual ~_XYList(){}    int Count();//实际有效的数据点    int CountAll();//所有的数据点,包括被移除的记录    int getRemoveCount(){ return  m_removeCount; }    _COORDINATEVALUE &getPoint(int index);    void addData(const double Key,const double Value);    void removefirst();    void cleanBuff();    int size() const { return m_CoodValue.size()-m_removeCount; }    QVector<_COORDINATEVALUE> *data();    void setPointCountMax(int Count);    int getPointMax(){ return m_MaxPointCount; }    void setColor(QColor color){ m_Color=color; }    QColor getColor(){ return m_Color; }    void setAxisType(_TICKERTYPE type){ m_Type=type; }    _TICKERTYPE &getAixsType(){ return m_Type; }    int getBegindex(const double &TmpKey);    int getEndindex(const double &TmpKey);    int getCoorToIndex(const double &TmpKey);    _COORDINATEVALUE getTrackValue(){ return TrackValue; }    void setTrackValue(const _COORDINATEVALUE value){ TrackValue=value; }    void setTrackValue(const double key,const double value){        TrackValue.Key=key;        TrackValue.Value=value;    }    bool TracckIsValid(){ return IsValid; }    void setTrackIsvalid(bool val){ IsValid=val; }    void setVisible(bool val){ m_Visible=val; }    bool getVisible(){ return m_Visible; }    _COORDINATEVALUE getMaxValue(){ return m_MaxValue; }    _COORDINATEVALUE getMinValue(){ return m_MinValue; }    QVector<_COORDINATEVALUE>::const_iterator constBegIte(){ return (m_CoodValue.begin()+m_removeCount); }    QVector<_COORDINATEVALUE>::const_iterator constEndIte(){ return m_CoodValue.end(); }protected:    QVector<_COORDINATEVALUE> m_CoodValue;    int m_MaxPointCount;//实际数据点,根据总数据点是否达到这和数目而对m_removeCount进行操作    int m_removeCount;//被移除的次数,会先记录,到达一定数据时候会重新分分配m_CoodValue大小,提高了添加固定点数据时候的速度    _TICKERTYPE m_Type;    QColor m_Color;    _COORDINATEVALUE TrackValue;//踪点的值    bool IsValid;//判断跟踪点的值是否有效    bool m_Visible;//是否绘制,既可见度    _COORDINATEVALUE m_MaxValue;    _COORDINATEVALUE m_MinValue;};/** * @brief The Ticker class * 坐标轴数据结构类,这里描述了坐标的主刻度,子刻度,刻度长度, * 坐标范围,坐标轴的类型(X还是Y 参考_TICKERTYPE)等信息 */class Ticker{public:    explicit Ticker()    {       MainLineCount=15;       SubLineCount=6;       Mainlength=10;       Sublength=10;       Type=_TICKERTYPE::XAxis;       m_RangeBeg=0;       m_RangeEnd=500;    }    virtual ~Ticker(){}    void setMainLineCount(const int count){ MainLineCount=count; }    void setSubLineCount(const int count){ SubLineCount=count; }    void setMainLineLength(const int length){ Mainlength=length; }    void setSubLineLength(const int length){ Sublength=length; }    void setAxisType(_TICKERTYPE type){ Type=type; }    void setTextType(_TEXT_TYPE Type){ m_TextType=Type; }    void setRangeBeg(const double &Value);    void setRangeEnd(const double &Value);    void setRange(const double &BegValue,const double &EndValue);    void moveRange(const double &Value);//根据数值偏移,正数往前,负数往后    void moveRangePercent(const double &Value);//根据百分比偏移,正数往前,负数往后    void setZoom(const double value);//根据中心值进行缩放,大于1表示放大,小于1表示缩小    int getMainLineCount(){ return MainLineCount; }    int getSubLineCount(){ return SubLineCount; }    int getMainLineLength(){ return Mainlength; }    int getSubLineLength(){ return Sublength; }    _TICKERTYPE getAxisType(){ return Type; }    double getRangeBeg(){ return m_RangeBeg; }    double getRangeEnd(){ return m_RangeEnd; }    double getRangeMidvalue(){ return (m_RangeBeg+(m_RangeEnd-m_RangeBeg)/2.0); }//获取轴的中心值    _Scale &getScale(){ return m_Scale; }    void InitScale();    void setScaleCoor(const double scaleFactor);//根据siteVal左边点进行缩放    _TEXT_TYPE getTextType(){ return m_TextType; }protected:    int MainLineCount;    int SubLineCount;    int Mainlength;    int Sublength;    double m_RangeBeg;    double m_RangeEnd;    _TICKERTYPE Type;    _TEXT_TYPE m_TextType;    _Scale m_Scale;private:   friend class CoorAxis;};#endif // ADDPOINT_H

头文件mainwindow.h

#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include "qtimer.h"#include "plot.h"#include <QLabel>QT_BEGIN_NAMESPACEnamespace Ui { class MainWindow; }QT_END_NAMESPACEclass MainWindow : public QMainWindow{    Q_OBJECTpublic:    MainWindow(QWidget *parent = nullptr);    ~MainWindow();public slots:    void slots_TimeOut();    void slots_Refresh();    void slots_UpdateTrack();protected:    QTimer *m_Timer;    QTimer *m_TimerRefresh;    CurveWid *m_Curve;    QVector<QLabel *> m_labList;    bool IsAddOk=false;private:    Ui::MainWindow *ui;};#endif // MAINWINDOW_H

c文件

#include "mainwindow.h"#include "ui_mainwindow.h"#include <QDateTime>#include <QDebug>#include "qgridlayout.h"#include "math.h"#include "qpainter.h"#include <QVBoxLayout>#include <QGridLayout>#define _POINTCOUNT 50000MainWindow::MainWindow(QWidget *parent)    : QMainWindow(parent)    , ui(new Ui::MainWindow){    ui->setupUi(this);    ui->statusbar->hide();    ui->centralwidget->setStyleSheet("QWidget{background-color: rgb(0, 0, 0);}");    m_Curve=new CurveWid;    connect(m_Curve->m_Plot,&Plot::sig_UpdateTrack,this,&MainWindow::slots_UpdateTrack);    m_Timer=new QTimer(this);    m_TimerRefresh=new QTimer(this);    m_Timer->start(100);    m_TimerRefresh->start(100);    connect(m_Timer,&QTimer::timeout,this,&MainWindow::slots_TimeOut);    connect(m_TimerRefresh,&QTimer::timeout,this,&MainWindow::slots_Refresh);    m_Curve->m_AxisL->ticker()->setRange(-100,1200);    m_Curve->m_AxisR->ticker()->setRange(-100,600);    m_Curve->m_AxisX->ticker()->setRange(-100,_POINTCOUNT*0.01);    qint64 Time=QDateTime::currentMSecsSinceEpoch();    m_Curve->m_AxisX->ticker()->setTextType(_TEXT_TYPE::_TimeMs);//    m_Curve->m_AxisX->ticker()->setRange(Time-600000,Time);    QGridLayout *G_layout=new QGridLayout;    G_layout->setVerticalSpacing(3);    G_layout->setContentsMargins(0,0,0,0);    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));    for(int i=0;i<16;i++)    {        QLabel *labValue=new QLabel;        labValue->setText(QString("Qlabel %1").arg(i+1));        labValue->setAlignment(Qt::AlignCenter);        labValue->setStyleSheet("QLabel{color:rgb(0, 122, 255);}");        labValue->setFixedHeight(36);        G_layout->addWidget(labValue,i/8,i%8);        QColor color=QColor(qrand() % 256, qrand() % 256, qrand() % 256);        int r,g,b;        color.getRgb(&r,&g,&b);        labValue->setStyleSheet(QString("QLabel{ color:rgb(%0,%1,%2);}").arg(r).arg(g).arg(b));        m_labList.append(labValue);        m_Curve->m_Plot->addGraph();        m_Curve->m_Plot->Graph(i)->setColor(color);        m_Curve->m_Plot->Graph(i)->setPointCountMax(_POINTCOUNT);        if((i%2)!=0){            m_Curve->m_Plot->Graph(i)->setAxisType(_TICKERTYPE::YAxis_R);        }else{            m_Curve->m_Plot->Graph(i)->setAxisType(_TICKERTYPE::YAxis_L);        }    }    QVBoxLayout *V_layout=new QVBoxLayout;    V_layout->setContentsMargins(0,0,0,0);    V_layout->addWidget(m_Curve);    V_layout->addLayout(G_layout);    ui->centralwidget->setLayout(V_layout);    for(int i=0;i<_POINTCOUNT*0.01;i++){        slots_TimeOut();    }    IsAddOk=true;}MainWindow::~MainWindow(){    delete ui;}void MainWindow::slots_TimeOut(){    double w = (3.14/100)*5;  //w为角速度 ,可以理解为波浪的密度,越大密度越大    double A = 40;    //  A表示振幅,可以理解为水波的高度,越大高度越高    static double x;    x++;    double waveY = (double)(A * sin(w * x ));// waveY随着x的值改变而改变,从而得到正弦曲线    static double count=0;    count+=1;    qint64 Time=QDateTime::currentMSecsSinceEpoch();    for(int i=0;i<m_Curve->m_Plot->getGraphCount();i++)    {        int num = qrand()%(200-100)+100;//产生300-500范围的随机岁        float data=0;//除以10获取 30.0到50.0的随机数        data+=80*i+num;//        m_Curve->m_Plot->Graph(i)->addData(count,data);        m_Curve->m_Plot->Graph(i)->addData(count,waveY+80*i);    }    if(IsAddOk)    {        if(count>m_Curve->m_AxisX->ticker()->getRangeEnd())        {            m_Curve->m_AxisX->ticker()->moveRange(count-m_Curve->m_AxisX->ticker()->getRangeEnd());        }    }}void MainWindow::slots_Refresh(){    m_Curve->reUpdateAll();}void MainWindow::slots_UpdateTrack(){    for(int i=0;i<m_Curve->m_Plot->getGraphCount();i++){        m_labList[i]->setText(QString::number(m_Curve->m_Plot->Graph(i)->getTrackValue().Value,'f',2));    }}

源码下载

工程:TestCurve
链接: 源码下载

到此这篇关于Qt自定义Plot实现曲线绘制的文章就介绍到这了,更多相关Qt自定义曲线绘制内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net!


Python 正则模块详情
python模块与C和C++动态库相互调用实现过程示例
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。