QcustomPlot 多条单条曲线光标自动更随的实现

QcustomPlot 多条单条曲线光标自动更随的实现QcustomPlot光标跟随最近有一个需求是能绘制多条曲线且能光标跟随,上网搜了很多相关的资料,如下边这个博客中查到了鼠标更随的相关代码,他的图如下所示——[原文链接地址](https://blog.csdn.net/sunnyloves/article/details/82344815)还有一篇如下所示——[原文链接地址](https://www.cnblogs.com…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

QcustomPlot光标跟随

最近有一个需求是能绘制多条曲线且能光标跟随,上网搜了很多相关的资料,如下边这个博客中查到了鼠标更随的相关代码,他的图如下所示——原文链接


QcustomPlot 多条单条曲线光标自动更随的实现

还有一篇如下所示——原文链接


QcustomPlot 多条单条曲线光标自动更随的实现

第一篇博主的实现方法其实已经比较完善了但是我按照他的方法去做后构造函数有点问题,所以对其做了一些修改之后得到如下结果——


QcustomPlot 多条单条曲线光标自动更随的实现
三条每条100万数据点曲线实时追踪无延迟,边界跳0无数据,本文所用为QcustomPlot2.0.1。 首先说的是对上边所提第一篇博客做的修改,代码如下

#ifndef MYTRACER_H
#define MYTRACER_H

#include <QObject>
#include "qcustomplot.h"
enum TracerType
{ 
   
    XAxisTracer,
    YAxisTracer,
    DataTracer
};

class myTracer : public QObject
{ 
   
    Q_OBJECT
public:



public:
    explicit myTracer(QCustomPlot *_plot,QCPGraph *_graph, TracerType _type);//这里与原贴不同,按照原贴构造总是过不去
    ~myTracer();

    void setPen(const QPen &pen);
    void setBrush(const QBrush &brush);
    void setText(const QString &text);
    void setLabelPen(const QPen &pen);
    void updatePosition(double xValue, double yValue);

protected:
    void setVisible(bool visible);
protected:
    QCustomPlot *plot ;	     //传入实例化的QcustomPlot
    QCPGraph *graph;	   	 //这里是存传入的绘图图层
    QCPItemTracer *tracer;   // 跟踪的点
    QCPItemText *label;   	 // 显示的数值
    QCPItemLine *arrow;  	 // 箭头

    TracerType type;
    bool visible;

signals:

public slots:

};

#endif // MYTRACER_H
#include "mytracer.h"

myTracer::myTracer(QCustomPlot *_plot, QCPGraph *_graph, TracerType _type) : plot(_plot),
    graph(_graph),
    type(_type),
    visible(false)

{ 
   
    if (plot)
    { 
   
        tracer = new QCPItemTracer(plot);
        tracer->setStyle(QCPItemTracer::tsPlus);//可以选择设置追踪光标的样式,这个是小十字,还有大十字,圆点等样式
// tracer->setPen(QPen(Qt::red));
        tracer->setPen(graph->pen());//设置tracer的颜色
        tracer->setBrush(graph->pen().color());
        tracer->setSize(10);

        label = new QCPItemText(plot);
        label->setLayer("overlay");
        label->setClipToAxisRect(false);
        label->setPadding(QMargins(5, 5, 5, 5));

        label->position->setParentAnchor(tracer->position);
        label->setFont(QFont("宋体", 10));

        arrow = new QCPItemLine(plot);
        arrow->setLayer("overlay");
        arrow->setPen(graph->pen());//设置箭头的颜色
        arrow->setClipToAxisRect(false);
        arrow->setHead(QCPLineEnding::esSpikeArrow);

        switch (type) { 
   
        case XAxisTracer:
        { 
   
            tracer->position->setTypeX(QCPItemPosition::ptPlotCoords);
            tracer->position->setTypeY(QCPItemPosition::ptAxisRectRatio);
            label->setBrush(QBrush(QColor(244, 244, 244, 100)));
            label->setPen(QPen(Qt::black));

            label->setPositionAlignment(Qt::AlignTop|Qt::AlignHCenter);

            arrow->end->setParentAnchor(tracer->position);
            arrow->start->setParentAnchor(arrow->end);
            arrow->start->setCoords(20, 0);//偏移量
            break;
        }
        case YAxisTracer:
        { 
   
            tracer->position->setTypeX(QCPItemPosition::ptAxisRectRatio);
            tracer->position->setTypeY(QCPItemPosition::ptPlotCoords);

            label->setBrush(QBrush(QColor(244, 244, 244, 100)));
            label->setPen(QPen(Qt::black));
            label->setPositionAlignment(Qt::AlignRight|Qt::AlignHCenter);

            arrow->end->setParentAnchor(tracer->position);
            arrow->start->setParentAnchor(label->position);
            arrow->start->setCoords(-20, 0);//偏移量
            break;
        }
        case DataTracer:
        { 
   
            tracer->position->setTypeX(QCPItemPosition::ptPlotCoords);
            tracer->position->setTypeY(QCPItemPosition::ptPlotCoords);

            label->setBrush(QBrush(QColor(244, 244, 244, 150)));
            label->setPen(graph->pen());
            label->setPositionAlignment(Qt::AlignLeft|Qt::AlignVCenter);

            arrow->end->setParentAnchor(tracer->position);
            arrow->start->setParentAnchor(arrow->end);
            arrow->start->setCoords(25, 0);
            break;
        }

        default:
            break;
        }

        setVisible(false);
    }
}

myTracer::~myTracer()
{ 
   
    if (tracer)
        plot->removeItem(tracer);
    if (label)
        plot->removeItem(label);
}

void myTracer::setPen(const QPen &pen)
{ 
   
    tracer->setPen(pen);
    arrow->setPen(pen);
}

void myTracer::setBrush(const QBrush &brush)
{ 
   
    tracer->setBrush(brush);
}

void myTracer::setLabelPen(const QPen &pen)
{ 
   
    label->setPen(pen);
}

void myTracer::setText(const QString &text)
{ 
   
    label->setText(text);
}

void myTracer::setVisible(bool visible)
{ 
   
    tracer->setVisible(visible);
    label->setVisible(visible);
    arrow->setVisible(visible);
}

void myTracer::updatePosition(double xValue, double yValue)
{ 
   
    if (!visible)
    { 
   
        setVisible(true);
        visible = true;
    }
    if (yValue > plot->yAxis->range().upper)
        yValue = plot->yAxis->range().upper;
    switch (type) { 
   
    case XAxisTracer:
    { 
   
        tracer->position->setCoords(xValue, 1);
        label->position->setCoords(0, 15);
        arrow->start->setCoords(0, 15);
        arrow->end->setCoords(0, 0);

        break;
    }
    case YAxisTracer:
    { 
   
        tracer->position->setCoords(1, yValue);
        label->position->setCoords(-20, 0);
        break;
    }
    case DataTracer:
    { 
   
        tracer->position->setCoords(xValue, yValue);
        label->position->setCoords(25, 0);
        break;
    }
    default:
        break;
    }
}

附上我的实现主函数

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QTextStream>
#include <string>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{ 
   
    ui->setupUi(this);


    m_Plot = QSharedPointer<QCustomPlot> (new QCustomPlot());
    ui->verticalLayout->addWidget(m_Plot.data());
    //设置基本坐标轴(左侧Y轴和下方X轴)可拖动、可缩放、曲线可选、legend可选、设置伸缩比例,使所有图例可见
    m_Plot->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom| QCP::iSelectAxes
                                |QCP::iSelectLegend | QCP::iSelectPlottables);
    m_Plot->legend->setVisible(true);
    m_Plot->legend->setFont(QFont("Helvetica",9));
    m_Plot->legend->setBrush(QColor(255,255,255,100));


    // generate some data:
    QVector<double> x(1000001), y(1000001), y1(1000001), y2(1000001);
    for (int i=0; i<1000001; ++i)
    { 
   
      x[i] = i;
      y[i] = x[i]/50000 * x[i]/50000;
      y1[i] = y[i] * 1.2;
      y2[i] = y[i] * 1.4;
    }
    QVector<QVector<double> > vec;
    vec.push_back(x);
    vec.push_back(y);
    m_value.push_back(vec);
    QVector<QVector<double> >().swap(vec);
    vec.push_back(x);
    vec.push_back(y1);
    m_value.push_back(vec);
    QVector<QVector<double> >().swap(vec);
    vec.push_back(x);
    vec.push_back(y2);
    m_value.push_back(vec);
    QVector<QVector<double> >().swap(vec);

    StaticDataPlot(m_value);
    m_Plot->xAxis->rescale(true);
    m_Plot->axisRect()->axis(QCPAxis::atBottom, 0)->setPadding(10); // add some padding to have space for tags

    m_TraserX = QSharedPointer<myTracer> (new myTracer(m_Plot.data(), m_Plot->graph(0), XAxisTracer));
    connect(m_Plot.data(), SIGNAL(mouseMove(QMouseEvent*)), this,SLOT(showTracer(QMouseEvent*)));
    m_Plot->replot();

}

MainWindow::~MainWindow()
{ 
   
    delete ui;
}

void MainWindow::showTracer(QMouseEvent *event)
{ 
   
    double x = m_Plot->xAxis->pixelToCoord(event->pos().x());
    m_TraserX->updatePosition(x, 0);
    m_TraserX->setText(QString::number(x, 'f', 2));
    for(int i=0;i<m_Graph.size();i++)
    { 
   
        double y = 0;
        QSharedPointer<QCPGraphDataContainer> tmpContainer;
        tmpContainer = m_Graph[i]->data();
        //使用二分法快速查找所在点数据!!!敲黑板,下边这段是重点
        int low = 0, high = tmpContainer->size();
        while(high > low)
        { 
   
            int middle = (low + high) / 2;
            if(x < tmpContainer->constBegin()->mainKey() ||
                    x > (tmpContainer->constEnd()-1)->mainKey())
                break;

            if(x == (tmpContainer->constBegin() + middle)->mainKey())
            { 
   
                y = (tmpContainer->constBegin() + middle)->mainValue();
                break;
            }
            if(x > (tmpContainer->constBegin() + middle)->mainKey())
            { 
   
                low = middle;
            }
            else if(x < (tmpContainer->constBegin() + middle)->mainKey())
            { 
   
                high = middle;
            }
            if(high - low <= 1)
            { 
      //差值计算所在位置数据
                y = (tmpContainer->constBegin()+low)->mainValue() + ( (x - (tmpContainer->constBegin() + low)->mainKey()) *
                    ((tmpContainer->constBegin()+high)->mainValue() - (tmpContainer->constBegin()+low)->mainValue()) ) /
                    ((tmpContainer->constBegin()+high)->mainKey() - (tmpContainer->constBegin()+low)->mainKey());
                break;
            }

        }

        m_Tracer[i]->updatePosition(x, y);
        m_Tracer[i]->setText(QString::number(y, 'f', 2));
    }
    m_Plot->replot();
}

介于很多小伙伴找我咨询代码问题,找到之前面目全非的代码重新修改编译了一下,可能有一点小不同但是效果相同,小手点下关注再去下载哦~
CustomPlotTest.zip

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/181226.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Spring+Struts+Hibernate 简介(转)

    Spring+Struts+Hibernate 简介(转)

    2021年9月10日
    65
  • python微信推送{u‘errcode‘: 40008, u‘errmsg‘: u‘invalid message type rid: 6111061f-19703d5b[通俗易懂]

    python微信推送{u‘errcode‘: 40008, u‘errmsg‘: u‘invalid message type rid: 6111061f-19703d5b[通俗易懂]记录一下前两天自己搞的一个蠢事,当时是要做一个微信信息推送,我先是按照微信的接口文档和网上的一些例子把代码写好了,测试的时候一直报这个40008,看微信接口文档又是说消息类型不对,大概就是说你给的data跟你定义的模板格式不对但是我都对了好几次,发现没问题,后面检查了一下接口的链接,发现跟接口文档里的不一样,应该是在复制别人的时候复制错了,换成文档里的链接后就正常了。所以,以后遇到这种{u’errcode’:40008,u’errmsg’:u’invalidmessagetyperid:

    2022年6月10日
    66
  • HTML5 新特性_CSS3新特性

    HTML5 新特性_CSS3新特性一.HTML5概念:1.什么是HTML5:(1)HTML5将成为HTML、XHTML以及HTMLDOM的新标准;(2)HTML5仍处于完善之中。然而,大部分现代浏览器已经具备了某些HTML5支持。2.HTML5的起步:(1)HTML5是W3C(WorldWideWebConsortium,万维网联盟)与WHATWG合作的结果(2)为HTML5建立的…

    2025年6月18日
    1
  • 我用Python采集了班花的空间数据集,除了美照竟然再一次发现了她另外的秘密![通俗易懂]

    大家好,我是辣条。室友知道了我上次给班花修过电脑,追了我三条街,嘴里大骂我不当人子,怪我这种事情没带他。最后又舔着脸求我支招,这货竟然想追班花!辣条我为了兄弟两(收)肋(钱)插(办)刀(事),毫不犹豫的答应了。但是我只有班花的QQ和微信怎么办呢,那就从她平时发的动态着手,于是就有了这篇文章,不过最后我又发现了她的另一秘密!采集数据目标网址:QQ空间工具使用开发环境:win10、python3.7开发工具:pycharm、Chrome工具包:selenium,re,time.

    2022年4月13日
    39
  • 通过pycharm使用git和github的步骤(图文详解)[通俗易懂]

    通过pycharm使用git和github的步骤(图文详解)[通俗易懂]目录:导读一、在Pycharm工具中配置集成Git和GitHub。二、推送项目到版本库三、从版本库克隆项目四、通过文件名颜色识别文件状态。五、如何向Git和GitHub仓库中添加文件?六、如何修改Git仓库中的文件?七、如何删除Git仓库中的文件?八、创建分支九、总结一、在Pycharm工具中配置集成Git和GitHub。1.集成Git。打开Pycharm,点击File–>Settins–>VersionControl–>Git.

    2022年8月26日
    5
  • 前端如何获取当前时间_js 获取年份

    前端如何获取当前时间_js 获取年份前端js获取当前时间的方法:vartime=newDate();time.getYear();//获取当前年份time.getFullYear();//获取完整的年份(4位,1970-???)time.getMonth();//获取当前月份(0-11,0代表1月)time.getDate();//获取当前日(1-31)tim…

    2022年9月23日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号