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

一、前言

 

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

二、开发环境

我的开发环境是QT5.10+MSVC2015

QCustomPlot 2.0

三、准备&参考文章

附上对我最有帮助的文章链接:QcustomPlot 多条单条曲线光标自动更随的实现_Bing_Lee的博客-CSDN博客_qtgraph 光标

附上参考文章的参考文章( 主要是评论区博主那句话对我起到了开导作用,要不然也是一直卡住了):QCustomPlot鼠标跟随显示坐标值_洗洗睡去的博客-CSDN博客_qcustomplot 显示坐标

附上QCustomPlot修改颜色文章:Qt之qcustomplot背景色改变_小师兄.的博客-CSDN博客_qcustomplot 背景色

附上QCustomPlot各种坐标轴类的使用文章:Qt由入门到放弃-QCustomPlot之QCPAxisTicker坐标轴类(一)_bwangk的博客-CSDN博客_qcpaxistickertime

四、正文

各位看官如果是准备使用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.csdn.net/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

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

五、结语&效果

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

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

  • 46
    点赞
  • 215
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大桶矿泉水

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值