Qt由入门到放弃-QCustomPlot之QCPAxisTicker坐标轴类(一)

       Qt由入门到放弃-QCustomPlot绘制天气曲线图并动态显示曲线坐标值(二)

      由于项目需要,实现天气预报的曲线绘制功能,进而学习了QCustomPlot的第三方控件,这里浅尝辄止的分享一下自己对QCPAxisTicker坐标轴类的使用,先上图看QCPAxisTicker的几种用法:

Qt由入门到放弃-QCustomPlot之QCPAxisTicker坐标轴类(一)_第1张图片

一、QCPAxisTicker基类

QCPAxisTicker是坐标轴的基类,它的属性和方法如下,其中有刻度轴步长显示策略TickStepStrategy的枚举类型,可参考此篇文章QCustomplot使用分享(六) 坐标轴和网格线:

class QCPAxisTicker
{
  
public:
  /*!
    定义选择坐标轴步长策略
  */
  enum TickStepStrategy
  {
    tssReadability    //具有更好可读性的(由系统分配)刻度步长匹配优先于自定义分配刻度数目匹配
    ,tssMeetTickCount //使用setTickCount()函数设置用户自定义的刻度数目
  };
  // getters:
  TickStepStrategy tickStepStrategy() const { return mTickStepStrategy; }//获得刻度匹配策略
  int tickCount() const { return mTickCount; }//返回刻度数
  double tickOrigin() const { return mTickOrigin; }//获得起点坐标偏移量
  // setters:
  void setTickStepStrategy(TickStepStrategy strategy);//设置刻度匹配策略
  void setTickCount(int count);//设置刻度数目
  void setTickOrigin(double origin);//设置起点坐标偏移量
  // introduced virtual methods:虚函数自定义生成坐标刻度
  virtua void generate(const QCPRange &range, const QLocale &locale, QChar formatChar, 
  int precision, QVector &ticks, QVector *subTicks, QVector *tickLabels);
  
protected:
  // property members:
  TickStepStrategy mTickStepStrategy;
  int mTickCount;
  double mTickOrigin;

  // 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 createTickVector(double tickStep, const QCPRange &range);//生成刻度向量
  virtual QVector createSubTickVector(int subTickCount, const QVector &ticks);//生成子刻度向量
  //生成刻度标签向量
  virtual QVector createLabelVector(const QVector &ticks,
  const QLocale &locale, QChar formatChar, int precision);
  
  // non-virtual methods:
  //trimTicks()从指定范围之外的刻中移除刻度坐标,如果keepOneOutlier==true,则在保留的刻度范围两边保留刻度标记
  void trimTicks(const QCPRange &range, QVector &ticks, bool keepOneOutlier) const;
  //pickClosest()返回包含在与所提供的目标最接近的候选坐标,此方法假定候选者不是空的,按升序排序
  double pickClosest(double target, const QVector &candidates) const;
  //getMantissa()返回输入的十进制尾数,例如142.6的输入将返回尾数1.426和100的大小。
  double getMantissa(double input, double *magnitude=0) const;
  //cleanMantissa()返回一个接近输入的数字,它有一个更简单的人类可读尾数
  double cleanMantissa(double input) const;
};

二、 QCPAxisTickerDateTime

1.QCPAxisTickerDateTime类是日期时间坐标轴

关于日期时间可看我前一篇Qt由入门到放弃-QDate、QTime、QDateTime的相关函数,具体方法如下所示:

class  QCPAxisTickerDateTime : public QCPAxisTicker
{
public:
 
  // getters:
  QString dateTimeFormat();//获得日期显示格式
  Qt::TimeSpec dateTimeSpec();//获得时区
  
  // setters:
  void setDateTimeFormat(const QString &format);//设置时间显示格式
  void setDateTimeSpec(Qt::TimeSpec spec);//设置时区
  void setTickOrigin(double origin); 
  void setTickOrigin(const QDateTime &origin);
  
  // static methods:
  static QDateTime keyToDateTime(double key);//时间戳转成日期
  static double dateTimeToKey(const QDateTime dateTime);//日期转成时间戳秒
  static double dateTimeToKey(const QDate date);//日期转成时间戳秒
  
protected:
  // property members:
  QString mDateTimeFormat;//格式化时间
  Qt::TimeSpec mDateTimeSpec;//时区
  
  // non-property members:
  enum DateStrategy //设置刻度策略
  {
	dsNone   //刻度不设置间距,默认大于等于一秒
	, dsUniformTimeInDay  //刻度间距大于等于一天
	, dsUniformDayInMonth  //刻度间距大于等于一月
  } mDateStrategy;
  
  // reimplemented 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 createTickVector(double tickStep, const QCPRange &range) ;
};

2.据此实现了一个小例子:

void setupTestQCPAxisTickerDateTime()
{
    customPlot->setInteraction(QCP::iRangeDrag, true);
    customPlot->setInteraction(QCP::iRangeZoom, true);
    QDateTime dateTime = QDateTime::currentDateTime();
    double  now = dateTime.toTime_t();//当前时间转化为秒
    //生成时间刻度对象
    QSharedPointer dateTimeTicker(new QCPAxisTickerDateTime);
    customPlot->xAxis->setTicker(dateTimeTicker);
    //dateTimeTicker->setDateTimeSpec(Qt::UTC);//设施世界时间,即不加上时区的时间
    dateTimeTicker->setTickCount(12);
    dateTimeTicker->setTickStepStrategy(QCPAxisTicker::tssMeetTickCount);
    customPlot->xAxis->setSubTicks(false);
    customPlot->xAxis->setRange(now, now+3600*24);//x轴范围,从当前时间起往后推24小时
    QVector yData, xData;//生成数据
    for (int i = 0; i <= 24; i++)
    {
        xData.push_back(now + i * 3600.0);
        yData.push_back(pow(double(i), 2) + 550.0*sin(double(i)/4.0));
    }
    dateTimeTicker->setDateTimeFormat("yyyy-M-d h:m");//设置x轴刻度显示格式
    customPlot->xAxis->setTickLabelRotation(30);//设置刻度标签顺时针旋转30度
    customPlot->yAxis->setRange(-1000,10000);
    customPlot->addGraph();
    customPlot->graph(0)->setData(xData, yData);//显示数据
}

3.运行结果图:

Qt由入门到放弃-QCustomPlot之QCPAxisTicker坐标轴类(一)_第2张图片

4.分析

QCPAxisTickerDateTime坐标轴默认是从时间戳起点即1970-1-1 0:0:0开始,以秒为单位进行刻度划分, 以下前两行代码为核心,获取当前秒数,通过第三行代码来设置时间范围。

QDateTime dateTime = QDateTime::currentDateTime();
double  now = dateTime.toTime_t();//当前时间转化为秒
customPlot->xAxis->setRange(now, now+3600*24);//x轴范围,从当前时间起往后推24小时

三、QCPAxisTickerTime

1.QCPAxisTickerTime是时间轴刻度类

class  QCPAxisTickerTime : public QCPAxisTicker
{

public:
  
  enum TimeUnit { tuMilliseconds ///< 毫秒(%z 在setTimeFormat中设置)
                  ,tuSeconds     ///< 秒 (%s)
                  ,tuMinutes     ///< 分钟 (%m)
                  ,tuHours       ///< 小时 (%h)
                  ,tuDays        ///< 天 (%d)
                };
  // getters:
  QString timeFormat();//获得时间显示格式
  int fieldWidth(TimeUnit unit) const { return mFieldWidth.value(unit); }
  
  // setters:
  void setTimeFormat(const QString &format);
  void setFieldWidth(TimeUnit unit, int width);//设置刻度间距宽度
  
protected:
  // property members:
  QString mTimeFormat;//时间格式化字符串
  QHash mFieldWidth;//时间宽度格式
  
  // non-property members:
  //最小的单位,最大的单位(如定义mSmallestUnit(tuSeconds),mBiggestUnit(tuHours))
  TimeUnit mSmallestUnit, mBiggestUnit;
  QHash mFormatPattern;
  
  // reimplemented 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) ;
  //对特定的值value用指定文本text替换时间单位
  void replaceUnit(QString &text, TimeUnit unit, int value) const;
};

2.据此实现了一个小例子:

void MainWindow::setupTestQCPAxisTickerTime()
{

    customPlot->setInteraction(QCP::iRangeDrag, true);
    customPlot->setInteraction(QCP::iRangeZoom, true);
    customPlot->rescaleAxes();

    QDateTime dateTime = QDateTime::currentDateTime();
    QString dataString = dateTime.toString("yyyy:M:dd:hh:mm:ss");
    qDebug()<<"*********"< timeTicker(new QCPAxisTickerTime);
    customPlot->xAxis->setTicker(timeTicker);
    timeTicker->setTickCount(6);
    //设置刻度表示策略
    timeTicker->setTickStepStrategy(QCPAxisTicker::tssMeetTickCount);
    customPlot->xAxis->setSubTicks(false);
    timeTicker->setTickOrigin(3600*3);//x轴起点坐标加3小时,即从当前hours+3开始
    customPlot->xAxis->setRange(hours*3600, hours*3600 +3600*12);
    customPlot->yAxis->setRange(-1000,1000);
    timeTicker->setTimeFormat("%dday-%hhour");

    QVector yData, xData;
    for (int i = 0; i <= 24; i++){
        xData.push_back(hours*3600 + i * 3600);
        yData.push_back(pow(double(i), 2) + 550.0*sin(double(i)/4.0));
    }
    customPlot->addGraph();
    customPlot->graph(0)->setData(xData, yData);

}

3.运行结果图:

Qt由入门到放弃-QCustomPlot之QCPAxisTicker坐标轴类(一)_第3张图片

4.分析

时间可以以毫秒、秒、分钟、小时和天显示。取决于通过setTimeFormat函数定义的最大可用单位,超过最大单位的。例如,如果格式字符串为"%M:%s",则为坐标值7815(2小时,10分钟和15秒)被创建,得到的刻度标签将显示"130:15"(130分钟,15秒)。如果格式字符串为"%H:%M:%s",则为"小时"。单位将被使用,标签将是“2:10:15”。

四、QCPAxisTickerText

1.QCPAxisTickerText是文本刻度标签

/*
设置文本刻度标签
*/
class QCPAxisTickerText : public QCPAxisTicker
{
public:
 
  // getters:
  QMap &ticks();//获得坐标轴标签
  int subTickCount();//获得子刻度数目
  
  // setters:
  void setTicks(const QMap &ticks);//坐标轴标签添加坐标轴
  void setTicks(const QVector &positions, const QVector labels);//坐标轴标签添加坐标轴
  void setSubTickCount(int subTicks);//设置子刻度数目
  
  // non-virtual methods:
  void clear();
  //addTick()坐标轴添加文本标签三种形式
  void addTick(double position, QString label);
  void addTicks(const QMap &ticks);
  void addTicks(const QVector &positions, const QVector &labels);
  
protected:
  // property members:
  QMap mTicks;//坐标轴标签
  int mSubTickCount;//子刻度数目
  
  // reimplemented 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 createTickVector(double tickStep, const QCPRange &range) ;
  
};

2.据此实现了一个小例子:

void MainWindow::setupTestQCPAxisTickerText()
{
    //画柱状图
    QCPBars *regen = new QCPBars(customPlot->xAxis, customPlot->yAxis);
    regen->setAntialiased(false); // gives more crisp, pixel aligned bar borders
    regen->setStackingGap(1);
    regen->setName("Regenerative");
    regen->setPen(QPen(QColor(0, 168, 140).lighter(130)));
    regen->setBrush(QColor(0, 168, 140));
    // stack bars on top of each other:
   // regen->moveAbove(nuclear);
    QVector ticks;
    QVector labels;
    ticks << 1 << 2 << 3 << 4 << 5 << 6 << 7;
    labels << "USA" << "Japan" << "Germany" << "France" << "UK" << "Italy" << "Canada";
    QSharedPointer textTicker(new QCPAxisTickerText);
    textTicker->addTicks(ticks, labels);
    customPlot->xAxis->setTicker(textTicker);
    customPlot->xAxis->setTickLabelRotation(60);
    customPlot->xAxis->setSubTicks(false);
    customPlot->xAxis->setTickLength(0, 4);
    customPlot->xAxis->setRange(0, 8);
    customPlot->xAxis->setTickPen(QPen(Qt::white));

    // prepare y axis:
    customPlot->yAxis->setRange(0, 12.1);
    customPlot->yAxis->setPadding(5); // a bit more space to the left border
    customPlot->yAxis->setLabel("Power Consumption in\nKilowatts per Capita (2007)");
    //customPlot->yAxis->setBasePen(QPen(Qt::white));
    customPlot->yAxis->setTickPen(QPen(Qt::white));
    customPlot->yAxis->setSubTickPen(QPen(Qt::white));
    // Add data:
    QVector  regenData;
    regenData   << 0.06*10.5 << 0.05*5.5 << 0.04*5.5 << 0.06*5.8 << 0.02*5.2 << 0.07*4.2 << 0.25*11.2;
    regen->setData(ticks, regenData);

}

3.运行结果图:

Qt由入门到放弃-QCustomPlot之QCPAxisTicker坐标轴类(一)_第4张图片

五、QCPAxisTickerPi

1.QCPAxisTickerPi设置Pi刻度标签

class  QCPAxisTickerPi : public QCPAxisTicker
{
  
public:

  enum FractionStyle { fsFloatingPoint     //分数被显示为规则十进制浮点数,例如“0.25”或“0.125”
                       ,fsAsciiFractions   //分数是用ASCII字符写成的有理数,例如“1/4”或“1/8”
                       ,fsUnicodeFractions //分数使用子和上标UTF-8数字和分数符号来编写
                     };

  QString piSymbol() const { return mPiSymbol; }//返回代替PI的符号标志
  double piValue() const { return mPiValue; }//返回PI表示的值
  bool periodicity() const { return mPeriodicity; }//是否周期性地出现
  FractionStyle fractionStyle() const { return mFractionStyle; }//轴上数据分数显示风格
  
  void setPiSymbol(QString symbol);//设置PI符号位的用symbol代替显示
  void setPiValue(double pi);//设置PI表示的值,不指定PI表示默认值3.1415926....
  //setPeriodicity()设置轴标签是否周期性地出现
  //若要禁用周期性,将multiplesOfPi设置为0。例如将轴定义0到2PI的周期则会将multiplesOfPi设置为2
  void setPeriodicity(int multiplesOfPi);
  //设置轴的分数显示形式
  void setFractionStyle(FractionStyle style);
  
protected:
  QString mPiSymbol;
  double mPiValue;
  int mPeriodicity;
  FractionStyle mFractionStyle;

  double mPiTickStep; // size of one tick step in units of mPiValue

  virtual double getTickStep(const QCPRange &range) ;
  virtual int getSubTickCount(double tickStep) ;
  virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) ;

  void simplifyFraction(int &numerator, int &denominator) const;//对给定的分子numerator,分母denominator化成最简真分数
  QString fractionToString(int numerator, int denominator) const;//转成字符串
  QString unicodeFraction(int numerator, int denominator) const;//转成unicode编码
  QString unicodeSuperscript(int number) const;//返回表示数字为上标的Unicode字符串
  QString unicodeSubscript(int number) const;//返回表示数字为下标的Unicode字符串
};

2.据此实现了一个小例子:

void MainWindow::setupTestQCPAxisTickerPi()
{
    QSharedPointer pITicker(new QCPAxisTickerPi());
    customPlot->xAxis->setTicker(pITicker);
    //pITicker->setPeriodicity(2);
    //pITicker->setPiSymbol("--");
    pITicker->setFractionStyle(QCPAxisTickerPi::fsUnicodeFractions);
    pITicker->setPiValue(3.1415*2);//设置pi表示的值
    customPlot->xAxis->setRange(0, 3.0*M_PI);
    customPlot->xAxis->setVisible(true);
    QVector x2(250), y2(250);
    for (int i=0; i<250; ++i) // data for graphs 2, 3 and 4
     {
       x2[i] = i/250.0*3*M_PI;
       y2[i] = qSin(x2[i]+ M_PI) + M_PI;
     }
    customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
    customPlot->graph(0)->setData(x2, y2);

}

3.运行结果图:

Qt由入门到放弃-QCustomPlot之QCPAxisTicker坐标轴类(一)_第5张图片

六、QCPAxisTickerLog

1.QCPAxisTickerLog设置log对数刻度标签

class  QCPAxisTickerLog : public QCPAxisTicker
{
public:
  QCPAxisTickerLog();
 
  double logBase() const { return mLogBase; }
  int subTickCount() const { return mSubTickCount; }
  
  void setLogBase(double base);//设置对数的基数值
  void setSubTickCount(int subTicks);//设置子刻度数目
  
protected:
  double mLogBase;
  int mSubTickCount;

  double mLogBaseLnInv;

  virtual double getTickStep(const QCPRange &range) ;
  virtual int getSubTickCount(double tickStep) ;
  virtual QVector createTickVector(double tickStep, const QCPRange &range) ;
};

2.据此实现了一个小例子:

void MainWindow::setupTestQCPAxisTickerLog()
{
    QSharedPointer logTicker(new QCPAxisTickerLog);
    customPlot->xAxis->setTicker(logTicker);
    // don't forget to also set the scale type accordingly, otherwise you'll have
    // logarithmically spaced ticks on a linear axis:
    customPlot->xAxis->setScaleType(QCPAxis::stLogarithmic);
    customPlot->xAxis->setRange(0,250);
    logTicker->setLogBase(10);
    QVector x2(250), y2(250);
    for (int i=0; i<250; ++i) // data for graphs 2, 3 and 4
     {
       x2[i] = i;
       y2[i] = log(i);
     }
    customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
    customPlot->graph(0)->setData(x2, y2);

}

3.运行结果图:

Qt由入门到放弃-QCustomPlot之QCPAxisTicker坐标轴类(一)_第6张图片

七、QCPAxisTickerFixed

1.QCPAxisTickerFixed定义轴标尺修改指定的步长控制坐标轴刻度的数目


class  QCPAxisTickerFixed : public QCPAxisTicker
{
  
public:
  
  enum ScaleStrategy { ssNone      //固定刻度,不允许修改
                       ,ssMultiples //设置刻度间距为整数倍长度
                       ,ssPowers    //设置刻度间距为指数倍长度
                     };

  // getters:
  double tickStep() const { return mTickStep; }
  ScaleStrategy scaleStrategy() const { return mScaleStrategy; }
  
  // setters:
  void setTickStep(double step);
  void setScaleStrategy(ScaleStrategy strategy);
  
protected:
  // property members:
  double mTickStep;
  ScaleStrategy mScaleStrategy;
  
  // reimplemented virtual methods:
  virtual double getTickStep(const QCPRange &range) ;
};

八、完整代码下载

点我下载

你可能感兴趣的:(Qt由入门到放弃)