基于QCustomPlot绘图,鼠标跟随动态显示曲线上的…
2018-12-11 09:02:56来源:博客园 阅读 ()
#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(5, 5, 5, 5));
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", 8));
m_label->setColor(clrDefault);
m_label->setText("");
m_arrow = new QCPItemLine(m_plot);
QPen arrowPen(clrDefault, 1);
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(7);
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(0, 20);//偏移量
break;
}
case YAxisTracer:
{
m_tracer->position->setTypeX(QCPItemPosition::ptAxisRectRatio);
m_tracer->position->setTypeY(QCPItemPosition::ptPlotCoords);
m_tracer->setSize(7);
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(-20, 0);//偏移量
break;
}
case DataTracer:
{
m_tracer->position->setTypeX(QCPItemPosition::ptPlotCoords);
m_tracer->position->setTypeY(QCPItemPosition::ptPlotCoords);
m_tracer->setSize(5);
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(20, 0);
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, 1);
m_label->position->setCoords(0, 15);
m_arrow->start->setCoords(0, 15);
m_arrow->end->setCoords(0, 0);
setText(QString::number(xValue));
break;
}
case YAxisTracer:
{
m_tracer->position->setCoords(0, yValue);
m_label->position->setCoords(-20, 0);
// 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(20, 0);
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, 1, 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(0, 0);
m_lineV->point2->setCoords(0, 0);
}
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(0, 0);
m_lineH->point2->setCoords(0, 0);
}
}
}
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 = 0); 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 = 0; 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(0); m_customPlot->plotLayout()->addElement(0, 0, new QCPTextElement(m_customPlot, "标题", QFont("黑体", 12, QFont::Bold))); m_customPlot->legend->setVisible(true); QFont legendFont = font(); // start out with MainWindow's font.. legendFont.setPointSize(9); // and make a bit smaller for legend m_customPlot->legend->setFont(legendFont); m_customPlot->legend->setBrush(QBrush(QColor(255,255,255,230))); // 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(0, 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 = 100; QVector<double> x(nCount), y0(nCount), y1(nCount); // initialize with entries 0..100 for (int i = 0; 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 = 1; 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
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:luogu P1816 【忠诚】
- C++冒泡排序 (基于函数模板实现) 2020-05-31
- C++抓图服务 2020-03-31
- #《Essential C++》读书笔记# 第四章 基于对象的编程风格 2020-02-08
- 开源项目SMSS开发指南(二)——基于libevent的线程池 2020-01-11
- 第四章 复合类型 2019-12-16
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash