话不多说时间匆忙直接步入正题,本博主要介绍qt用QCustomPlot实现曲线绘制然后 鼠标放在曲线上能实时显示坐标,之前研究这块,网上也有一些参考例程,但总的来说可参考的 文章 还是很少,所以这里就在多分享一章,贡献一份力量。
我的开发环境是QT5.10+MSVC2015
QCustomPlot 2.0
附上对我最有帮助的文章链接:https://blog.csdn.net/bing_lee/article/details/84037955#comments
附上参考文章的参考文章( 主要是评论区博主那句话对我起到了开导作用,要不然也是一直卡住了):https://blog.csdn.net/sunnyloves/article/details/82344815
附上QCustomPlot修改颜色文章:https://blog.csdn.net/u014252478/article/details/79928433
附上QCustomPlot各种坐标轴类的使用文章:https://blog.csdn.net/bwangk/article/details/81950598
各位看官如果是准备使用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
#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 xtemp,ytemp;
QSharedPointer 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 (new myTracer(CustomPlot, CustomPlot->graph(0), DataTracer));
//m_TraserX = QSharedPointer (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 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="<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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 m_TraserX;
QSharedPointer 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坐标显示分开,一种是在一起的,程序中都有相应的部分,只需打开相应的注释和注释相应的内容,就可以分别实现这两种方式了
代码链接:https://download.csdn.net/download/qq_37603131/11310167