一、概述

前边已经写了5篇对QCustomPlot的讲解,看过上述的几篇文章后,基本就能做一些简单的使用了,但是如果想要做到高度的控制图表,那么坐标轴将是很重要的一部分,因为坐标轴就是图表的一个参考系,没有了参考系那么一切都是天方夜谭。关于QCustomPlot的坐标轴我还是会按照之前的套路,首先对比1.3.2版本和2.0.0beta版本,然后在深入的去分析坐标轴使用。

二、历史版本对比

首先我需要和大家伙说明下,我个人觉着在QCustomPlot的定制过程中,坐标轴定制算是比较困难的,因为坐标轴如果要定制的话,那就是坐标轴的刻度需要自己计算,如果这个时候相关的业务逻辑也影响坐标轴的计算,那么就更难计算了,呵呵。。。或许大家伙可能也不会遇到这些问题,有兴趣的同学也可以自己思考下。

  1.3.2版本 2.0.0版本
坐标轴
1、QCPAxis:坐标轴类,所有坐标轴功能都在这一个类总实现,包括:刻度计算和绘制文本
2、默认刻度自动计算,负责计算大刻度和小刻度
3、如果需要外部计算刻度则处理ticksRequest请求
1、QCPAxis:坐标轴类,所有坐标轴功能都在这一个类总实现,包括:刻度计算和绘制文本
2、默认刻度自动计算,负责计算大刻度和小刻度
3、如果需要外部计算刻度则处理ticksRequest请求

表1 1.3.2版本和2.0.0版本坐标轴比较

下面我将针对2.0.0版本的坐标轴刻度计算来加以解释,为了方便起见,我只解释QCPAxisTicker这个坐标轴刻度计算基类,因为QCPAxis坐标轴默认使用的就是这个类,其余的坐标轴刻度计算类比如QCPAxisTickerDateTime、QCPAxisTickerTime、QCPAxisTickerFixed、QCPAxisTickerText、QCPAxisTickerPi和QCPAxisTickerLog等都是根据不同业务需求,重新实现了vitural相关方法。

三、坐标轴

1、QCPAxis,如下是QCPAxis的头文件,我从中删除了大量不需要注释的部分,但是很是剩下许多,为了写注释方便所以我没有把代码折叠,有兴趣的同学可以阅读下其中的中文注释,其实这个类仅仅是用来连接计算和绘制坐标轴的一个类,也可以说是暴露给使用者的一个导出类。

class QCP_LIB_DECL QCPAxis : public QCPLayerable
{enum AxisType {//坐标轴类型,在一个坐标轴矩形QCPAxisRect中包含左、上、右和下四条坐标轴atLeft = 0x01  ///< <tt>0x01</tt> Axis is vertical and on the left side of the axis rect, atRight = 0x02  ///< <tt>0x02</tt> Axis is vertical and on the right side of the axis rect, atTop = 0x04  ///< <tt>0x04</tt> Axis is horizontal and on the top side of the axis rect, atBottom = 0x08  ///< <tt>0x08</tt> Axis is horizontal and on the bottom side of the axis rect};enum LabelSide {//坐标轴刻度上的文本的位置,刻度线里or外lsInside    ///< Tick labels will be displayed inside the axis rect and clipped to the inner axis rect, lsOutside  ///< Tick labels will be displayed outside the axis rect};enum ScaleType {//坐标轴类型,直线or对数线stLinear       ///< Linear scaling, stLogarithmic ///< Logarithmic scaling with correspondingly transformed axis coordinates (possibly also \ref setTicker to a \ref QCPAxisTickerLog instance).};enum SelectablePart {/坐标轴可以被选中的部分spNone = 0      ///< None of the selectable parts, spAxis = 0x001  ///< The axis backbone and tick marks, spTickLabels = 0x002  ///< Tick labels (numbers) of this axis (as a whole, not individually), spAxisLabel = 0x004  ///< The axis label};explicit QCPAxis(QCPAxisRect *parent, AxisType type);virtual ~QCPAxis();//所有的get接口已经被我删除  看到对应的set接口,get接口的含义就不言而喻// setters:Q_SLOT void setScaleType(QCPAxis::ScaleType type);//设置坐标轴类型  直线or对数Q_SLOT void setRange(const QCPRange &range);//设置坐标轴范围void setRange(double lower, double upper); 33     void setTicker(QSharedPointer<QCPAxisTicker> ticker);//设置坐标轴计算刻度类,该参数是一个shared型智能指针,因此可以被多个坐标轴来同时使用void setTicks(bool show);//是否显示坐标轴,如果不显示坐标轴,那么网格线也就没有啦,因为没有了坐标轴刻度void setTickLabels(bool show);//是否显示坐标轴文本void setTickLabelPadding(int padding);//设置坐标走文本距离坐标轴线距离void setTickLabelFont(const QFont &font);//设置文本字体void setTickLabelColor(const QColor &color);//设置文本颜色void setTickLabelRotation(double degrees);//设置文本角度void setTickLabelSide(LabelSide side);//设置文本在刻度线里or外void setNumberFormat(const QString &formatCode);//设置文本格式void setNumberPrecision(int precision);//设置文本精度void setTickLength(int inside, int outside = 0);//设置大刻度高度void setTickLengthIn(int inside);//设置大刻度在里边长度void setTickLengthOut(int outside);//设置大刻度在外边长度void setSubTicks(bool show);//设置是否显示小刻度void setSubTickLength(int inside, int outside = 0);//设置小刻度高度void setSubTickLengthIn(int inside);//设置小刻度在坐标轴线里边长度void setSubTickLengthOut(int outside);//设置小刻度在坐标轴线外边长度void setBasePen(const QPen &pen);//设置基础线画笔  基础线是零线,即可以认为是坐标轴刻度为0的线void setTickPen(const QPen &pen);//设置大刻度画笔void setSubTickPen(const QPen &pen);//设置小刻度画笔void setLabelFont(const QFont &font);//设置坐标轴名称字体画笔void setLabelColor(const QColor &color);//设置坐标轴名称字体颜色void setLabel(const QString &str);//设置坐标轴名称文本void setLabelPadding(int padding);//设置坐标轴名称文本距离坐标轴刻度线距离void setPadding(int padding);//设置坐标轴距离边界距离void setOffset(int offset);//设置偏移量void setSelectedTickLabelFont(const QFont &font);//设置选中刻度文本时字体void setSelectedLabelFont(const QFont &font);//设置选中坐标轴名称时字体void setSelectedTickLabelColor(const QColor &color);//选中刻度文本时颜色void setSelectedLabelColor(const QColor &color);//选中坐标轴名称时颜色void setSelectedBasePen(const QPen &pen);//选中基础线时画笔void setSelectedTickPen(const QPen &pen);//选中大刻度时画笔void setSelectedSubTickPen(const QPen &pen);//选中小刻度时画笔Q_SLOT void setSelectableParts(const QCPAxis::SelectableParts &selectableParts);//设置能选中项的类型Q_SLOT void setSelectedParts(const QCPAxis::SelectableParts &selectedParts);void setLowerEnding(const QCPLineEnding &ending);//设置坐标轴小刻度端样式void setUpperEnding(const QCPLineEnding &ending);//坐标轴大刻度端样式 73// non-property methods:Qt::Orientation orientation() const { return mOrientation; }//坐标轴朝向int pixelOrientation() const { return rangeReversed() != (orientation() == Qt::Vertical) ? -1 : 1; }void moveRange(double diff);//移动坐标轴void scaleRange(double factor);//按比例因子缩放void scaleRange(double factor, double center);//按范围缩放 81     void rescale(bool onlyVisiblePlottables = false);//重新适配坐标轴范围double pixelToCoord(double value) const;//像素到坐标轴坐标系double coordToPixel(double value) const;//坐标轴坐标系到像素 85     QList<QCPAbstractPlottable*> plottables() const;//所有的图QList<QCPGraph*> graphs() const;//所有的折线QList<QCPAbstractItem*> items() const;//所有的示意项 92
protected:AxisType mAxisType;//坐标轴类型QCPAxisRect *mAxisRect;//坐标轴所在矩形116// non-property members:QCPGrid *mGrid;//网格120     QSharedPointer<QCPAxisTicker> mTicker;//坐标轴刻度计算类QVector<double> mTickVector;//大刻度QVector<QString> mTickVectorLabels;//大刻度文本QVector<double> mSubTickVector;//小刻度bool mCachedMarginValid;int mCachedMargin;// introduced virtual methods:virtual int calculateMargin();// reimplemented virtual methods:virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE;//获取缺省的反锯齿属性virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE;//画坐标轴virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE;//选择策略137// non-virtual methods:void setupTickVectors();//计算刻度QPen getBasePen() const;//获取基础画笔QPen getTickPen() const;//获取大刻度画笔QPen getSubTickPen() const;//获取小刻度画笔QFont getTickLabelFont() const;//获取刻度文本画笔QFont getLabelFont() const;//获取坐标轴名称文本字体QColor getTickLabelColor() const;//获取大刻度文本颜色QColor getLabelColor() const;..获取坐标轴名称文本颜色
};

具体的绘制类其实是QCPAxisPainterPrivate类,这是一个私有类,从名字就可以看出,他是一个QCPAxis类的绘制私有类,事实确实如此。刻度计算类是QCPAxisTicker,这是一个刻度计算基类,也是QCPAxis默认使用的刻度计算类,当然了这个类还有一大堆子类,都是专门用于生成指定类型的坐标轴。

2、QCPAxisTicker:刻度计算类,该类完成了大刻度、小刻度和大刻度文本的计算,供QCPAxis来调用绘制,其中generate方法是一个公有的虚方法,既可以被重写,又可以被外部调用,QCPAxis坐标轴就是调用该接口来重新计算刻度。

class QCP_LIB_DECL QCPAxisTicker
{Q_GADGET
public:enum TickStepStrategy//刻度生成策略{tssReadability    ///< A nicely readable tick step is prioritized over matching the requested number of ticks (see \ref setTickCount), tssMeetTickCount ///< Less readable tick steps are allowed which in turn facilitates getting closer to the requested tick count};QCPAxisTicker();virtual ~QCPAxisTicker();// setters:void setTickStepStrategy(TickStepStrategy strategy);//设置刻度生成策略void setTickCount(int count);//设置大刻度个数 有可能计算出来的刻度数不完全等于设置的刻度个数,取决于刻度生成策略void setTickOrigin(double origin);//设置坐标轴领刻度// introduced virtual methods:virtual void generate(const QCPRange &range, const QLocale &locale, QChar formatChar, int precision, QVector<double> &ticks, QVector<double> *subTicks, QVector<QString> *tickLabels);protected:// introduced virtual methods:virtual double getTickStep(const QCPRange &range);//根据坐标轴范围计算步长virtual int getSubTickCount(double tickStep);//根据步长计算自刻度个数virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision);//根据指定语言、文本格式和精度获取文本virtual QVector<double> createTickVector(double tickStep, const QCPRange &range);//生成大刻度virtual QVector<double> createSubTickVector(int subTickCount, const QVector<double> &ticks);//生成小刻度virtual QVector<QString> createLabelVector(const QVector<double> &ticks, const QLocale &locale, QChar formatChar, int precision);//生成刻度文本// non-virtual methods:void trimTicks(const QCPRange &range, QVector<double> &ticks, bool keepOneOutlier) const;//去除无效的刻度值double pickClosest(double target, const QVector<double> &candidates) const;//该函数返回范围内第一个不小于(大于或等于)指定target的值。
};

四、网格线

QCPGrid网格线,这个算是和QCPAxis坐标轴类似的实现,和其他模块关系基本都不是很大,直接继承自QCPLayerable,头文件格式如下,同样的,我删除了其中无需注释的一部分代码。

在QCustomPlot的源码设计中,一个QCPAxis坐标轴对于一个QCPGrid,这同我之前理解的图表绘制有些不大一样,呵呵呵。。。但是QCustomPlot就是这么干了,如果想对网格线做一些控制,有时候从QCPAxis就可以做到,因为他们直接的数据在使用上还是比较依赖。

class QCP_LIB_DECL QCPGrid :public QCPLayerable
{QCPGrid(QCPAxis *parentAxis);// setters:void setSubGridVisible(bool visible);//设置是否显示自网格线void setAntialiasedSubGrid(bool enabled);//设置子网格线是否反锯齿void setAntialiasedZeroLine(bool enabled);//设置零线(就是刻度值为0的线)是否反锯齿void setPen(const QPen &pen);//设置画笔void setSubGridPen(const QPen &pen);//设置子网格画笔void setZeroLinePen(const QPen &pen);//设置零线画笔protected:bool mSubGridVisible;//子网格是否显示标记bool mAntialiasedSubGrid, mAntialiasedZeroLine;//子网格和零线是否反锯齿标记QPen mPen, mSubGridPen, mZeroLinePen;//这个就不用说了QCPAxis *mParentAxis;//对于的坐标轴,一个网格线对应一个坐标轴virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const;//获取缺省的反锯齿属性virtual void draw(QCPPainter *painter);//绘制网格线,内部调用drawGridLines和drawSubGridLines// non-virtual methods:void drawGridLines(QCPPainter *painter) const;//绘制网格线void drawSubGridLines(QCPPainter *painter) const;//绘制子网格线
};

一般来说,网格线不需要重写,顶多就是设置一个颜色,控制是否显示,网格线的疏密成都市和坐标轴刻度计算有关系的,因此关于网格线的计算我们就不要考虑了,下面我提供一个我自定义的刻度固定像素计算类示例

五、简单的示例

首先来看下效果,如图1所示,当图表放大时,y轴上的刻度间距是保持固定像素的。

图1 y轴固定像素伸缩

如下是刻度计算类头文件,这个类实现起来还是比较简单的,根据屏幕像素返回步长,每次步长都是按当前像素比例下计算的。

class AxisFixedPixelTicker : public QCPAxisTicker
{
public:AxisFixedPixelTicker(QCPAxis * axis);~AxisFixedPixelTicker();public:void SetTickPixelStep(int pixel);//设置固定像素int GetTickPixelStep() const;//获取固定像素大小protected://QCPAxisTickervirtual double getTickStep(const QCPRange & range) override;//重写父类方法,根据固定像素返回步长值private:QScopedPointer<AxisFixedPixelTickerPrivate> d_ptr;
};

下面是重写的父类接口getTickStep方法实现

double AxisFixedPixelTicker::getTickStep(const QCPRange & range)
{if (d_ptr->m_pDependAxis){bool vertical;if (d_ptr->m_pDependAxis->axisType() == QCPAxis::atLeft|| d_ptr->m_pDependAxis->axisType() == QCPAxis::atRight){vertical = true;}else{vertical = false;}int screenLength = vertical ? d_ptr->m_pDependAxis->axisRect()->rect().height() : d_ptr->m_pDependAxis->axisRect()->rect().width();return d_ptr->m_iPixel * range.size() / screenLength;}else{return __super::getTickStep(range);}
}

QCustomplot 坐标轴和网格线相关推荐

  1. python使用matplotlib可视化:设置坐标轴的范围、设置主次坐标轴刻度、坐标轴刻度显示样式、坐标轴刻度数颜色、小数点位数、坐标轴刻度网格线、线条类型、数据点形状标签、文本字体、颜色、大小等

    python使用matplotlib可视化:设置坐标轴的范围.设置主次坐标轴刻度.坐标轴刻度显示样式.坐标轴刻度数颜色.小数点位数.坐标轴刻度网格线.线条类型.数据点形状标签.文本字体.颜色.大小等 ...

  2. qcustomplot时间坐标轴画直线_QCustomplot使用分享(六) 坐标轴和网格线

    一.概述 前边已经写了5篇对QCustomPlot的讲解,看过上述的几篇文章后,基本就能做一些简单的使用了,但是如果想要做到高度的控制图表,那么坐标轴将是很重要的一部分,因为坐标轴就是图表的一个参考系 ...

  3. QCustomplot使用分享(六) 坐标轴和网格线

    文章目录 一.概述 二.历史版本对比 三.坐标轴 四.网格线 五.简单的示例 六.相关文章 一.概述 前边已经写了5篇对QCustomPlot的讲解,看过上述的几篇文章后,基本就能做一些简单的使用了, ...

  4. QCustomplot笔记(二)之QCustomplot 坐标轴属性设置

    一.前言 记录分享楼主学习QCustomplot的过程,楼主最近查看了坐标轴的一些属性设置,于是便记录下 属性设置不一定全,也不一定都对,不喜勿喷 二.坐标轴属性类别 1.设置坐标是否显示 ui-&g ...

  5. QCustomPlot 坐标轴添加单位

    为坐标轴添加单位需要修改库代码 目标类: QCPAxis 在类中, 定义成员变量 QString m_format; 然后定义函数: void setAxisFormat(QString format ...

  6. QCustomPlot坐标轴反向

    下面是效果图 参考代码: QString xFile = param["x_data"].toString();QString yFile = param["y_data ...

  7. 怎么给QCustomPlot 坐标轴添加单位

    效果图: 添加 void setAxisFormat(QString format): 添加函数 setAxisFormat(QString format): 修改draw 函数 添加变量 m_for ...

  8. 数据分析36计 :Uber的 A/B 实验平台搭建

    公众号后台回复"图书",了解更多号主新书内容 作者:数据狗 来源:DataGo数据狗 实验是Uber如何改善客户体验的核心.Uber将多种实验方法应用于各种用例,例如测试一项新功能 ...

  9. 数据分析36计(17):Uber的 A/B 实验平台搭建

    往期系列原创文章集锦: 数据分析36计(16):和 A/B 测试同等重要的观察性研究:群组研究 VS 病例-对照方法 数据分析36计(15):这个序贯检验方法让 A/B 实验节约一半样本量 数据分析3 ...

最新文章

  1. HDU4738(割点)
  2. linux下Makefile的简单例子及解释
  3. 关于 mac m1 xcode12 编译报错 this target. for architecture arm64等问题解决方案
  4. 1.5 编程基础之循环控制 10 满足条件的数累加
  5. D3 selectselectAll
  6. iOS开发中的单元测试(三)——URLManager中的测试用例解析
  7. 用Map集合来统计一个字符串数组中每个字符串的个数
  8. Java全国计算机等级考试二级笔记---操作题部分
  9. STC - 非标连接的7段数码管赋值
  10. iOS-Runtime之SEL、IMP、Method
  11. S-Paper电子纸在生产车间中的应用
  12. 与“十“俱进 阿里数据库运维10年演进之路 1
  13. H5页面嵌套在APP中的坑
  14. 【转】maven Failure to find xxx in 中央仓库
  15. Linux用户安全及Linux PAM验证机制
  16. 博士毕业选择回老家县城大专任教!事业编、副教授待遇、外加几十万安家费......
  17. nmcli命令及team链路聚合
  18. RPA优势解密丨到底能做什么?为何深受追捧?
  19. java如何打印当前月份日历_java打印指定年月份的日历
  20. python实现FP-growth算法发现频繁项集

热门文章

  1. pjax是更改所有的ajax,coffce-pjax
  2. GRU(门控循环单元),易懂。
  3. 数字大作战:宽带报障系列之错误633
  4. python 重命名的方法,python如何重命名文件
  5. 吉林大学操作系统上机(实验一:Linux进程与线程通讯)
  6. 计算机桌面打开为缩小模式,电脑桌面屏幕缩小了怎么办
  7. 不愿长大的人,总是在瞬间长大
  8. 最短路径问题---Dijkstra算法详解
  9. JavaFX Button常用相关属性和制作多边形按钮Button
  10. 在过去的一年里区块链领域最大的遗憾是什么了