QCustomPlot实现鼠标跟随显示xy坐标值

目录

1. 前言

2. 开发环境

3. 准备&参考文章

4. 正文

5. 结语&效果

6. 说明 


1. 前言

       话不多说时间匆忙直接步入正题,本博主要介绍qt用QCustomPlot实现曲线绘制然后 鼠标放在曲线上能实时显示坐标,之前研究这块,网上也有一些参考例程,但总的来说可参考的 文章 还是很少,所以这里就在多分享一章,贡献一份力量。

2. 开发环境

我的开发环境是

  • QT5.10+MSVC2015
  • QCustomPlot 2.0

3. 准备&参考文章

      附上对我最有帮助的文章链接:QcustomPlot 多条单条曲线光标自动更随的实现。附上参考文章的参考文章( 主要是评论区博主那句话对我起到了开导作用,要不然也是一直卡住了):QCustomPlot鼠标跟随显示坐标值

4. 正文

       各位看官如果是准备使用QCustomPlot 的话,就需要mytracer文件夹和QCustomPlot文件夹的内容,其中的两个文件我会打包到资源中提供各位下载。mainwindow就不完全开源了, 只开源QCustomPlot使用的部分

先附上代码, 多余的也不用我说,说了也是累赘,详细的我都写在了代码的注释中,一眼就能看懂

mytracer.cpp

#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::tsCircle);//可以选择设置追踪光标的样式,这个是小十字,还有大十字,圆点等样式
        tracer->setPen(QPen(Qt::green));//设置tracer的颜色绿色
        //tracer->setPen(graph->pen());//设置tracer的颜色跟曲线
        tracer->setBrush(QPen(Qt::green).color());
        tracer->setSize(6);
 
        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->setPen(QPen(Qt::red));//设置箭头的颜色红色
        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->setPen(QPen(Qt::red));//边框红色
            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,const QString &text1)
{
    label->setText(tr("X:%1mS\nY:%2V").arg(text).arg(text1));
}
/*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;
    }
}
 

 mytracer.h

#ifndef MYTRACER_H
#define MYTRACER_H
 
#include <QObject>
#include "QCustomPlot/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,const QString &text1);
    //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

QCustomPlot是2.0版本的, 其内容无修改,不 放代码,太长了。

mainwindow.cpp

//全局定义
float line9[2000];
 
 
//初始化
    for(int i=0;i<2000;i++)
       line9[i]=0.0075*i;
    SimpleDemo9(ui->widget9,1);
 
 
/*********************曲线配置************************/
void MainWindow::SimpleDemo9(QCustomPlot *CustomPlot,char mode)
{
    QVector<double> xtemp,ytemp;
    QSharedPointer<QCPAxisTickerPi> pITicker(new QCPAxisTickerPi());//QCPAxisTickerPi设置Pi刻度标签,详细参考:https://blog.youkuaiyun.com/bwangk/article/details/81950598
    CustomPlot->yAxis->setTicker(pITicker);
    pITicker->setPiSymbol("V");//设置数值后面π替换为V
    pITicker->setFractionStyle(QCPAxisTickerPi::fsFloatingPoint);//设置小数部分显示float型
    pITicker->setPiValue(1);//设置V表示的值
 
    //数据处理与显示
    if(mode==0);
    else{
        for(int i=0;i<2000;i++)
        {
            xtemp<< i;
            ytemp<< line9[i];
        }
    }
    //CustomPlot->xAxis->setVisible(false);//设置x轴不可见
    CustomPlot->addGraph();
    CustomPlot->xAxis->setRange(0,2000);//设置x轴范围
    CustomPlot->yAxis->setRange(0,15);//设置y轴范围
    CustomPlot->xAxis->setLabel("时间(mS)");//设置x轴名称
    CustomPlot->yAxis->setLabel("幅度(V)");//设置y轴名称
    CustomPlot->xAxis->setLabelColor(QColor(226,60,255));//设置x轴名称颜色
    CustomPlot->yAxis->setLabelColor(QColor(226,60,255));//设置y轴名称颜色
    CustomPlot->graph(0)->setPen(QPen(QColor(226,60,255)));//设置曲线颜色
    CustomPlot->graph(0)->setData(xtemp,ytemp);
 
    CustomPlot->xAxis->setTickLabelColor(Qt::yellow);//设置x轴坐标颜色
    CustomPlot->yAxis->setTickLabelColor(Qt::yellow);//设置y轴坐标颜色
    CustomPlot->xAxis->setBasePen(QPen(QColor(0,0,0)));//设置x轴坐标轴颜色
    CustomPlot->yAxis->setBasePen(QPen(QColor(25,150,92)));//设置y轴坐标轴颜色
    //设置画布背景色
    QLinearGradient plotGradient;
    plotGradient.setStart(0, 0);
    plotGradient.setFinalStop(0, 350);
    plotGradient.setColorAt(0, QColor(80, 80, 80));
    plotGradient.setColorAt(1, QColor(50, 50, 50));
    CustomPlot->setBackground(plotGradient);
 
    //CustomPlot->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom| QCP::iSelectAxes|QCP::iSelectLegend | QCP::iSelectPlottables);//如有多条曲线可选中,暂时只有一条曲线,先不用这个功能,因为选中会卡一些
    CustomPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);//可以进行鼠标位置 放大缩小 拖拽  放大缩小坐标系
 
    m_TracerY = QSharedPointer<myTracer> (new myTracer(CustomPlot, CustomPlot->graph(0), DataTracer));
    //m_TraserX = QSharedPointer<myTracer> (new myTracer(CustomPlot, CustomPlot->graph(0), XAxisTracer));
    connect(CustomPlot, SIGNAL(mouseMove(QMouseEvent*)), this,SLOT(showTracer(QMouseEvent*)));
    CustomPlot->replot();//重绘 每次改变完以后都要调用这个进行重新绘制
}
void MainWindow::showTracer(QMouseEvent *event)
{
    double x = ui->widget9->xAxis->pixelToCoord(event->pos().x());
 
    //for(int i=0;i<1;i++)//ui->widget9->graph(0)->dataCount()
    //{
       double y = 0;
       QSharedPointer<QCPGraphDataContainer> tmpContainer;
       tmpContainer = ui->widget9->graph(0)->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;
           }
 
       }
       //qDebug()<<"y="<<y;
       //显示x轴的鼠标动态坐标
       //m_TraserX->updatePosition(x, 0);
       //m_TraserX->setText(QString::number(x, 'f', 0));
       //显示y轴的鼠标动态坐标,缺点无法定位xy所以无法附加单位,附加单位仍需继续修改setText传参
       //m_TracerY->updatePosition(x, y);
       //m_TracerY->setText(QString::number(y, 'f', 2));
       //由原来的x,y分别显示改为x,y显示在一起,xy单位直接在setText中设置好
       m_TracerY->updatePosition(x, y);
       m_TracerY->setText(QString::number(x, 'f', 0),QString::number(y, 'f', 2));//x轴取整数,y轴保留两位小数
 
    //}
    ui->widget9->replot();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QFile>
#include <QApplication>
#include <QMainWindow>
#include <QtSql>
#include <QSqlQuery>
#include <QSqlTableModel>
#include <QSerialPort>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QProcess>
#include <QUrl>
#include <QDesktopServices>
#include <QVector>
#include <QSharedPointer>
#include "QCustomPlot/qcustomplot.h"
#include "MyTracer/mytracer.h"
 
 
namespace Ui {
class MainWindow;
}
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
 
private slots:
 
    //曲线部分
    void SimpleDemo9(QCustomPlot *customPlot,char mode);//绘制曲线
    void showTracer(QMouseEvent *event);
 
 
private:
    Ui::MainWindow *ui;
 
    QSharedPointer<myTracer> m_TraserX;
    QSharedPointer<myTracer> m_TracerY;
 
};
 
#endif // MAINWINDOW_H

pro文件

#-------------------------------------------------
#
# Project created by QtCreator 2019-06-07T17:00:41
#
#-------------------------------------------------
 
QT       += core gui sql serialport
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
 
TARGET = untitled
TEMPLATE = app
 
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
 
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 
 
SOURCES += \
        main.cpp \
        mainwindow.cpp \
    QCustomPlot/qcustomplot.cpp \
    MyTracer/mytracer.cpp
 
HEADERS += \
        mainwindow.h \
    QCustomPlot/qcustomplot.h \
    MyTracer/mytracer.h
 
FORMS += \
        mainwindow.ui
 
CONFIG += mobility
MOBILITY = 
 
RESOURCES += \
    res.qrc
 
INCLUDEPATH += $$PWD/QCustomPlot
INCLUDEPATH += $$PWD/MyTracer

 基本是把功能全贴上了,相当满意把,满意就给个赞哦,支持一下,只为学习。

5. 结语&效果

好了,以上就是实现的全部代码了,放上两种效果图,一种是xy坐标显示分开,一种是在一起的,程序中都有相应的部分,只需打开相应的注释和注释相应的内容,就可以分别实现这两种方式了

代码链接:qt用QCustomPlot实现鼠标实时回调xy轴数据并显示在曲线内need.rar_qt绘制曲线左右移动的y轴-QT代码类资源-优快云下载

6. 说明 

本文转自qt之QCustomPlot实现鼠标跟随显示xy坐标值,xy轴类型等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值