采用Qt快速绘制多条曲线(折线),跟随鼠标动态显示线上点的值(基于Qt的开源绘图控件QCustomPlot进行二次开发)
- #ifndef MYTRACER_H
- #define MYTRACER_H
- #include <QObject>
- #include "qcustomplot.h"
- ///
- /// \brief The XxwTracer class:在图表中显示鼠标所在位置的x,y值的追踪显示器
- ///
- class XxwTracer : public QObject
- {
- Q_OBJECT
- public:
- enum TracerType
- {
- XAxisTracer,//依附在x轴上显示x值
- YAxisTracer,//依附在y轴上显示y值
- DataTracer//在图中显示x,y值
- };
- explicit XxwTracer(QCustomPlot *_plot, TracerType _type, QObject *parent = Q_NULLPTR);
- ~XxwTracer();
- 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);
- void setVisible(bool m_visible);
- protected:
- bool m_visible;//是否可见
- TracerType m_type;//类型
- QCustomPlot *m_plot;//图表
- QCPItemTracer *m_tracer;//跟踪的点
- QCPItemText *m_label;//显示的数值
- QCPItemLine *m_arrow;//箭头
- };
- ///
- /// \brief The XxwCrossLine class:用于显示鼠标移动过程中的鼠标位置的直线
- ///
- class XxwTraceLine : public QObject
- {
- public:
- enum LineType
- {
- VerticalLine,//垂直线
- HorizonLine, //水平线
- Both//同时显示水平和垂直线
- };
- explicit XxwTraceLine(QCustomPlot *_plot, LineType _type = VerticalLine, QObject *parent = Q_NULLPTR);
- ~XxwTraceLine();
- void initLine();
- void updatePosition(double xValue, double yValue);
- void setVisible(bool vis)
- {
- if(m_lineV)
- m_lineV->setVisible(vis);
- if(m_lineH)
- m_lineH->setVisible(vis);
- }
- protected:
- bool m_visible;//是否可见
- LineType m_type;//类型
- QCustomPlot *m_plot;//图表
- QCPItemStraightLine *m_lineV; //垂直线
- QCPItemStraightLine *m_lineH; //水平线
- };
- #endif // MYTRACER_H
源文件MyTracer.cpp
- #include "MyTracer.h"
- XxwTracer::XxwTracer(QCustomPlot *_plot, TracerType _type, QObject *parent)
- : QObject(parent),
- m_plot(_plot),
- m_type(_type)
- {
- m_visible = true;
- m_tracer = Q_NULLPTR;// 跟踪的点
- m_label = Q_NULLPTR;// 显示的数值
- m_arrow = Q_NULLPTR;// 箭头
- if (m_plot)
- {
- QColor clrDefault(Qt::red);
- QBrush brushDefault(Qt::NoBrush);
- QPen penDefault(clrDefault);
- // penDefault.setBrush(brushDefault);
- penDefault.setWidthF(0.5);
- m_tracer = new QCPItemTracer(m_plot);
- m_tracer->setStyle(QCPItemTracer::tsCircle);
- m_tracer->setPen(penDefault);
- m_tracer->setBrush(brushDefault);
- m_label = new QCPItemText(m_plot);
- m_label->setLayer("overlay");
- m_label->setClipToAxisRect(false);
- m_label->setPadding(QMargins(, , , ));
- m_label->setBrush(brushDefault);
- m_label->setPen(penDefault);
- m_label->position->setParentAnchor(m_tracer->position);
- // m_label->setFont(QFont("宋体", 8));
- m_label->setFont(QFont("Arial", ));
- m_label->setColor(clrDefault);
- m_label->setText("");
- m_arrow = new QCPItemLine(m_plot);
- QPen arrowPen(clrDefault, );
- m_arrow->setPen(penDefault);
- m_arrow->setLayer("overlay");
- m_arrow->setClipToAxisRect(false);
- m_arrow->setHead(QCPLineEnding::esSpikeArrow);//设置头部为箭头形状
- switch (m_type)
- {
- case XAxisTracer:
- {
- m_tracer->position->setTypeX(QCPItemPosition::ptPlotCoords);
- m_tracer->position->setTypeY(QCPItemPosition::ptAxisRectRatio);
- m_tracer->setSize();
- m_label->setPositionAlignment(Qt::AlignTop | Qt::AlignHCenter);
- m_arrow->end->setParentAnchor(m_tracer->position);
- m_arrow->start->setParentAnchor(m_arrow->end);
- m_arrow->start->setCoords(, );//偏移量
- break;
- }
- case YAxisTracer:
- {
- m_tracer->position->setTypeX(QCPItemPosition::ptAxisRectRatio);
- m_tracer->position->setTypeY(QCPItemPosition::ptPlotCoords);
- m_tracer->setSize();
- m_label->setPositionAlignment(Qt::AlignRight | Qt::AlignHCenter);
- m_arrow->end->setParentAnchor(m_tracer->position);
- m_arrow->start->setParentAnchor(m_label->position);
- m_arrow->start->setCoords(-, );//偏移量
- break;
- }
- case DataTracer:
- {
- m_tracer->position->setTypeX(QCPItemPosition::ptPlotCoords);
- m_tracer->position->setTypeY(QCPItemPosition::ptPlotCoords);
- m_tracer->setSize();
- m_label->setPositionAlignment(Qt::AlignLeft | Qt::AlignVCenter);
- m_arrow->end->setParentAnchor(m_tracer->position);
- m_arrow->start->setParentAnchor(m_arrow->end);
- m_arrow->start->setCoords(, );
- break;
- }
- default:
- break;
- }
- setVisible(false);
- }
- }
- XxwTracer::~XxwTracer()
- {
- if(m_plot)
- {
- if (m_tracer)
- m_plot->removeItem(m_tracer);
- if (m_label)
- m_plot->removeItem(m_label);
- if (m_arrow)
- m_plot->removeItem(m_arrow);
- }
- }
- void XxwTracer::setPen(const QPen &pen)
- {
- if(m_tracer)
- m_tracer->setPen(pen);
- if(m_arrow)
- m_arrow->setPen(pen);
- }
- void XxwTracer::setBrush(const QBrush &brush)
- {
- if(m_tracer)
- m_tracer->setBrush(brush);
- }
- void XxwTracer::setLabelPen(const QPen &pen)
- {
- if(m_label)
- {
- m_label->setPen(pen);
- m_label->setBrush(Qt::NoBrush);
- m_label->setColor(pen.color());
- }
- }
- void XxwTracer::setText(const QString &text)
- {
- if(m_label)
- m_label->setText(text);
- }
- void XxwTracer::setVisible(bool vis)
- {
- m_visible = vis;
- if(m_tracer)
- m_tracer->setVisible(m_visible);
- if(m_label)
- m_label->setVisible(m_visible);
- if(m_arrow)
- m_arrow->setVisible(m_visible);
- }
- void XxwTracer::updatePosition(double xValue, double yValue)
- {
- if (!m_visible)
- {
- setVisible(true);
- m_visible = true;
- }
- if (yValue > m_plot->yAxis->range().upper)
- yValue = m_plot->yAxis->range().upper;
- switch (m_type)
- {
- case XAxisTracer:
- {
- m_tracer->position->setCoords(xValue, );
- m_label->position->setCoords(, );
- m_arrow->start->setCoords(, );
- m_arrow->end->setCoords(, );
- setText(QString::number(xValue));
- break;
- }
- case YAxisTracer:
- {
- m_tracer->position->setCoords(, yValue);
- m_label->position->setCoords(-, );
- // m_arrow->start->setCoords(20, 0);
- // m_arrow->end->setCoords(0, 0);
- setText(QString::number(yValue));
- break;
- }
- case DataTracer:
- {
- m_tracer->position->setCoords(xValue, yValue);
- m_label->position->setCoords(, );
- setText(QString("x:%1,y:%2").arg(xValue).arg(yValue));
- break;
- }
- default:
- break;
- }
- }
- XxwTraceLine::XxwTraceLine(QCustomPlot *_plot, LineType _type, QObject *parent)
- : QObject(parent),
- m_type(_type),
- m_plot(_plot)
- {
- m_lineV = Q_NULLPTR;
- m_lineH = Q_NULLPTR;
- initLine();
- }
- XxwTraceLine::~XxwTraceLine()
- {
- if(m_plot)
- {
- if (m_lineV)
- m_plot->removeItem(m_lineV);
- if (m_lineH)
- m_plot->removeItem(m_lineH);
- }
- }
- void XxwTraceLine::initLine()
- {
- if(m_plot)
- {
- QPen linesPen(Qt::red, , Qt::DashLine);
- if(VerticalLine == m_type || Both == m_type)
- {
- m_lineV = new QCPItemStraightLine(m_plot);//垂直线
- m_lineV->setLayer("overlay");
- m_lineV->setPen(linesPen);
- m_lineV->setClipToAxisRect(true);
- m_lineV->point1->setCoords(, );
- m_lineV->point2->setCoords(, );
- }
- if(HorizonLine == m_type || Both == m_type)
- {
- m_lineH = new QCPItemStraightLine(m_plot);//水平线
- m_lineH->setLayer("overlay");
- m_lineH->setPen(linesPen);
- m_lineH->setClipToAxisRect(true);
- m_lineH->point1->setCoords(, );
- m_lineH->point2->setCoords(, );
- }
- }
- }
- void XxwTraceLine::updatePosition(double xValue, double yValue)
- {
- if(VerticalLine == m_type || Both == m_type)
- {
- if(m_lineV)
- {
- m_lineV->point1->setCoords(xValue, m_plot->yAxis->range().lower);
- m_lineV->point2->setCoords(xValue, m_plot->yAxis->range().upper);
- }
- }
- if(HorizonLine == m_type || Both == m_type)
- {
- if(m_lineH)
- {
- m_lineH->point1->setCoords(m_plot->xAxis->range().lower, yValue);
- m_lineH->point2->setCoords(m_plot->xAxis->range().upper, yValue);
- }
- }
- }
- #ifndef XCUSTOMPLOT_H
- #define XCUSTOMPLOT_H
- #include "XxwTracer.h"
- #include "qcustomplot.h"
- #include <QObject>
- #include <QList>
- class XxwCustomPlot:public QCustomPlot
- {
- Q_OBJECT
- public:
- XxwCustomPlot(QWidget *parent = );
- protected:
- virtual void mouseMoveEvent(QMouseEvent *event);
- public:
- ///
- /// \brief 设置是否显示鼠标追踪器
- /// \param show:是否显示
- ///
- void showTracer(bool show)
- {
- m_isShowTracer = show;
- if(m_xTracer)
- m_xTracer->setVisible(m_isShowTracer);
- foreach (XxwTracer *tracer, m_dataTracers)
- {
- if(tracer)
- tracer->setVisible(m_isShowTracer);
- }
- if(m_lineTracer)
- m_lineTracer->setVisible(m_isShowTracer);
- }
- ///
- /// \brief 是否显示鼠标追踪器
- /// \return
- ///
- bool isShowTracer(){return m_isShowTracer;};
- private:
- bool m_isShowTracer;//是否显示追踪器(鼠标在图中移动,显示对应的值)
- XxwTracer *m_xTracer;//x轴
- XxwTracer *m_yTracer;//y轴
- QList<XxwTracer *> m_dataTracers;//
- XxwTraceLine *m_lineTracer;//直线
- };
- #endif // XCUSTOMPLOT_H
源文件XCustomPlot.h
- #include "XxwCustomPlot.h"
- XxwCustomPlot::XxwCustomPlot(QWidget *parent)
- :QCustomPlot(parent)
- ,m_isShowTracer(false)
- ,m_xTracer(Q_NULLPTR)
- ,m_yTracer(Q_NULLPTR)
- ,m_dataTracers(QList<XxwTracer *>())
- ,m_lineTracer(Q_NULLPTR)
- {
- }
- void XxwCustomPlot::mouseMoveEvent(QMouseEvent *event)
- {
- QCustomPlot::mouseMoveEvent(event);
- if(m_isShowTracer)
- {
- //当前鼠标位置(像素坐标)
- int x_pos = event->pos().x();
- int y_pos = event->pos().y();
- //像素坐标转成实际的x,y轴的坐标
- float x_val = this->xAxis->pixelToCoord(x_pos);
- float y_val = this->yAxis->pixelToCoord(y_pos);
- if(Q_NULLPTR == m_xTracer)
- m_xTracer = new XxwTracer(this, XxwTracer::XAxisTracer);//x轴
- m_xTracer->updatePosition(x_val, y_val);
- if(Q_NULLPTR == m_yTracer)
- m_yTracer = new XxwTracer(this, XxwTracer::YAxisTracer);//y轴
- m_yTracer->updatePosition(x_val, y_val);
- int nTracerCount = m_dataTracers.count();
- int nGraphCount = graphCount();
- if(nTracerCount < nGraphCount)
- {
- for(int i = nTracerCount; i < nGraphCount; ++i)
- {
- XxwTracer *tracer = new XxwTracer(this, XxwTracer::DataTracer);
- m_dataTracers.append(tracer);
- }
- }
- else if(nTracerCount > nGraphCount)
- {
- for(int i = nGraphCount; i < nTracerCount; ++i)
- {
- XxwTracer *tracer = m_dataTracers[i];
- if(tracer)
- {
- tracer->setVisible(false);
- }
- }
- }
- for (int i = ; i < nGraphCount; ++i)
- {
- XxwTracer *tracer = m_dataTracers[i];
- if(!tracer)
- tracer = new XxwTracer(this, XxwTracer::DataTracer);
- tracer->setVisible(true);
- tracer->setPen(this->graph(i)->pen());
- tracer->setBrush(Qt::NoBrush);
- tracer->setLabelPen(this->graph(i)->pen());
- auto iter = this->graph(i)->data()->findBegin(x_val);
- double value = iter->mainValue();
- // double value = this->graph(i)->data()->findBegin(x_val)->value;
- tracer->updatePosition(x_val, value);
- }
- if(Q_NULLPTR == m_lineTracer)
- m_lineTracer = new XxwTraceLine(this,XxwTraceLine::Both);//直线
- m_lineTracer->updatePosition(x_val, y_val);
- this->replot();//曲线重绘
- }
- }
3 使用自定义图表类XCustomPlot
在需要绘图的地方使用,代码如下:
- m_customPlot = new XxwCustomPlot();
- m_customPlot->showTracer(true);
- // add title layout element:
- m_customPlot->plotLayout()->insertRow();
- m_customPlot->plotLayout()->addElement(, , new QCPTextElement(m_customPlot, "标题", QFont("黑体", , QFont::Bold)));
- m_customPlot->legend->setVisible(true);
- QFont legendFont = font(); // start out with MainWindow's font..
- legendFont.setPointSize(); // and make a bit smaller for legend
- m_customPlot->legend->setFont(legendFont);
- m_customPlot->legend->setBrush(QBrush(QColor(,,,)));
- // by default, the legend is in the inset layout of the main axis rect. So this is how we access it to change legend placement:
- m_customPlot->axisRect()->insetLayout()->setInsetAlignment(, Qt::AlignTop|Qt::AlignCenter);
- // make left and bottom axes always transfer their ranges to right and top axes:
- connect(m_customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), m_customPlot->xAxis2, SLOT(setRange(QCPRange)));
- connect(m_customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), m_customPlot->yAxis2, SLOT(setRange(QCPRange)));
- // Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
- m_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
- // generate some data:
- int nCount = ;
- QVector<double> x(nCount), y0(nCount), y1(nCount); // initialize with entries 0..100
- for (int i = ; i < nCount; ++i)
- {
- x[i] = i; // x goes from -1 to 1
- y0[i] = qSin(i * 10.0f / nCount); //sin
- y1[i] = qCos(i * 10.0f / nCount); //cos
- }
- // create graph and assign data to it:
- QPen pen;
- int i = ;
- QCPGraph *pGraph = m_customPlot->addGraph();
- // m_customPlot->graph(0)->setData(x, y0);
- pGraph->setName("sin曲线");
- pGraph->setData(x,y0);
- pGraph->setPen(QPen(Qt::blue));
- pGraph = m_customPlot->addGraph();
- // m_customPlot->graph(0)->setData(x, y0);
- pGraph->setName("cos曲线");
- pGraph->setData(x,y1);
- pGraph->setPen(QPen(Qt::darkYellow));
- // give the axes some labels:
- m_customPlot->xAxis->setLabel("x");
- m_customPlot->yAxis->setLabel("y");
- // set axes ranges, so we see all data:
- // m_customPlot->xAxis->setRange(-1, 1);
- // m_customPlot->yAxis->setRange(0, 1);
- m_customPlot->rescaleAxes(true);
- m_customPlot->replot();
4 效果图
本程序的源码下载地址: https://github.com/xiongxw/XCustomPlot.git
采用Qt快速绘制多条曲线(折线),跟随鼠标动态显示线上点的值(基于Qt的开源绘图控件QCustomPlot进行二次开发)的更多相关文章
- qt超强精美绘图控件 - QCustomPlot一览 及 安装使用教程
1.概述 QCustomPlot 是一个超强超小巧的qt绘图类,非常漂亮,非常易用,只需要加入一个qcustomplot.h和qcustomplot.cpp文件即可使用,远比qwt方便和漂亮,可以自己 ...
- paper 139:qt超强绘图控件qwt - 安装及配置
qwt是一个基于LGPL版权协议的开源项目, 可生成各种统计图.它为具有技术专业背景的程序提供GUI组件和一组实用类,其目标是以基于2D方式的窗体部件来显示数据, 数据源以数值,数组或一组浮点数等方式 ...
- C# Charts绘制多条曲线
一.创建winform工程 拖拽控件Chart 二.比如要绘制俩条曲线,设置Chart控件的属性Series 三.chart的属性根据自己的业务需求设计,我这里只设置了图标类型 代码: using S ...
- VS2010 使用TeeChart绘图控件 - 之二 - 绘制图形(折线图,柱状图)
1.前期准备 具体可见VS2010 使用TeeChart绘图控件 - 之一 控件和类的导入 1. 1 添加TeeChart控件,给控件添加变量m_TeeChart 添加TeeChart控件,右击控件, ...
- qt超强绘图控件qwt - 安装及配置
qwt是一个基于LGPL版权协议的开源项目, 可生成各种统计图.它为具有技术专业背景的程序提供GUI组件和一组实用类,其目标是以基于2D方式的窗体部件来显示数据, 数据源以数值,数组或一组浮点数等方式 ...
- MSChart绘图控件中折线图和柱形图画法
首先在前台拖入一个名为chart1的MSChart控件 //折线图 string strLegend = "Legend1"; Legend lg = new Legend(str ...
- 使用C#三维绘图控件快速搭建DXF查看程序
本例使用AnyCAD .Net三维图形控件快速实现一个DXF文件的读取.显示.导出JPG.PNG.PDF的应用. 代码: using System; using System.Collections. ...
- Qt绘图控件qwt绘制等比例坐标图
需要用到QwtPlotRescaler类,用法如下: QwtPlotRescaler *plotRescaler = new QwtPlotRescaler(canvas, yLeft, QwtPlo ...
- C#.NET常见问题(FAQ)-如何使用2D绘图控件ZedGraph绘制坐标轴和坐标曲线
添加数据:示例添加了一条sin曲线和一条cos曲线,注意cos曲线比sin曲线点更密集(可以用这种方式控制点的采样疏密程度) 默认显示效果如下图所示,可以框选一个部分看放大效果 右击某个点可以 ...
随机推荐
- 《Image-to-Image Translation with Conditional Adversarial Networks》论文笔记
出处 CVPR2017 Motivation 尝试用条件GAN网络来做image translation,让网络自己学习图片到图片的映射函数,而不需要人工定制特征. Introduction 作者从不 ...
- VScode相关
这就是我想要的 VSCode 插件! VS Code 快捷键(中英文对照版) visual studio code 配置vue开发环境 vscode 这样的注释怎么生成? 能让你开发效率翻倍的 VSC ...
- bzoj 2754: [SCOI2012]喵星球上的点名【AC自动机】
洛谷90,最后一个点死活卡不过去(也可能是我写的有问题? 比较暴力的做法,把询问带着标号建立AC自动机,用map存儿子. 然后用名字串在自动机上跑,以为是名或姓的子串就行所以把名和姓中间加个特殊字符拼 ...
- POJ 2259 Team Queue(队列)
题目原网址:http://poj.org/problem?id=2259 题目中文翻译: Description 队列和优先级队列是大多数计算机科学家已知的数据结构. 然而,Team Queue并不是 ...
- [Usaco2011 Feb]Generic Cow Protests
Description Farmer John's N (1 <= N <= 100,000) cows are lined up in a row and numbered 1..N. ...
- [USACO 2012 Jan Silver] Bale Share【DP】
传送门:http://www.usaco.org/index.php?page=viewproblem2&cpid=107 没想到太不应该了,真的不应该啊! f[i][j][k]表示前i个包, ...
- 题解报告:hdu 1236 排名
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1236 Problem Description 今天的上机考试虽然有实时的Ranklist,但上面的排名 ...
- ATM机(非函数版)
#include<stdio.h>#include<stdlib.h>int main(void){char zhangHao[]="123";int mi ...
- ES6知识点汇总
MDN镇楼: https://developer.mozilla.org/zh-CN/ 1.ES6新添加数据类型:symbol ----------- https://developer.moz ...
- c# 搜狗拼音输入法,刷输入速度和累计输入
事件起因: 搜狗拼音有几个称号(光速超人:要求最快打字速度 200字/m,一代文豪:要求累计输入字数达200000)一直没有那么快的速度,就想用.net来实现. 相关技术: 1.winform基本控件 ...