Qwt源码解读之标尺相关类

Qwt中添加标尺是非常方便和漂亮的。除了有普通的直尺外,还有环形标尺。这里我们先学习一下直尺的相关类。直尺的相关类共有下面几个:

1、QwtScaleMap:标尺值映射类。

QwtScaleMap类用于提供标尺坐标系与绘制设备坐标系之间的映射关系。其主要的功能依托 QwtScaleTransformation 类来实现。

2、QwtScaleDiv:标尺刻度划分类。

QwtScaleDiv类表征刻度划分。一个标尺的刻度划分包括它的起始值和3个刻度列表(分别为主刻度列表,次刻度列表和最小刻度列表)。大部分情况下,刻度划分是由QwtScaleEngine(应该说是由它的派生类)自动计算的。

3、QwtScaleDraw:绘制标尺类。

QwtScaleDraw类继承自抽象基类QwtAbstractScaleDraw,用于绘制普通标尺。一个标尺也由多个部分组成(如下列表),其由变量QwtAbstractScaleDraw::ScaleComponent 标识。

1)Backbone 标尺沿线。
2)Ticks 刻度线。
3)Labels 值标签。

4、QwtScaleWidget:标尺部件。

QwtScaleWidget类是呈现或者说被用于绘制标尺的部件,继承自QWidget。 在实际的开发中,这个类用得比较多。

代码分析:

1、QwtScaleTransformation 类

除了构造函数和习惯函数外,QwtScaleTransformation 类提供了以下接口:标尺坐标值与绘制设备坐标值之间的转化。
[cpp] view plain copy
  1. virtual double xForm( double s, double s1, double s2,
  2. double p1, double p2 ) const;
  3. virtual double invXForm( double p, double p1, double p2,
  4. double s1, double s2 ) const;

由于禁用了拷贝构造函数和拷贝赋值操作符函数,因此还提供了克隆函数:

[cpp] view plain copy
  1. //! Create a clone of the transformation
  2. QwtScaleTransformation *QwtScaleTransformation::copy() const
  3. {
  4. return new QwtScaleTransformation( d_type );
  5. }
2、QwtScaleMap类
这里看一下QwtScaleMap的拷贝构造函数和拷贝赋值操作符函数,帮助理解上面 QwtScaleTransformation类的copy()函数。

[cpp] view plain copy
  1. //! Copy constructor
  2. QwtScaleMap::QwtScaleMap( const QwtScaleMap& other ):
  3. d_s1( other.d_s1 ),
  4. d_s2( other.d_s2 ),
  5. d_p1( other.d_p1 ),
  6. d_p2( other.d_p2 ),
  7. d_cnv( other.d_cnv )
  8. {
  9. d_transformation = other.d_transformation->copy();
  10. }
  11. //! Assignment operator
  12. QwtScaleMap &QwtScaleMap::operator=( const QwtScaleMap & other )
  13. {
  14. d_s1 = other.d_s1;
  15. d_s2 = other.d_s2;
  16. d_p1 = other.d_p1;
  17. d_p2 = other.d_p2;
  18. d_cnv = other.d_cnv;
  19. delete d_transformation;
  20. d_transformation = other.d_transformation->copy();
  21. return *this;
  22. }
  23. //! Copy constructor
  24. QwtScaleMap::QwtScaleMap( const QwtScaleMap& other ):
  25. d_s1( other.d_s1 ),
  26. d_s2( other.d_s2 ),
  27. d_p1( other.d_p1 ),
  28. d_p2( other.d_p2 ),
  29. d_cnv( other.d_cnv )
  30. {
  31. d_transformation = other.d_transformation->copy();
  32. }
  33. //! Assignment operator
  34. QwtScaleMap &QwtScaleMap::operator=( const QwtScaleMap & other )
  35. {
  36. d_s1 = other.d_s1;
  37. d_s2 = other.d_s2;
  38. d_p1 = other.d_p1;
  39. d_p2 = other.d_p2;
  40. d_cnv = other.d_cnv;
  41. delete d_transformation;
  42. d_transformation = other.d_transformation->copy();
  43. return *this;
  44. }
然后,QwtScaleMap的参数设置接口和完成坐标系统之间值转化的功能函数:
[cpp] view plain copy
  1. void setPaintInterval( double p1, double p2 );
  2. void setScaleInterval( double s1, double s2 );
  3. double transform( double s ) const;
  4. double invTransform( double p ) const;
3、QwtScaleDiv类
QwtScaleDiv类共有3个构造函数,不带参数的默认构造函数创建一个“无效的”刻度划分实例。我们看具有两个参数的构造函数,就能明白了QwtScaleDiv的基本属性特征。

[cpp] view plain copy
  1. /*!
  2. Construct QwtScaleDiv instance.
  3. \param interval Interval
  4. \param ticks List of major, medium and minor ticks
  5. */
  6. QwtScaleDiv::QwtScaleDiv( const QwtInterval &interval,
  7. QList<double> ticks[NTickTypes] ):
  8. d_lowerBound( interval.minValue() ),
  9. d_upperBound( interval.maxValue() ),
  10. d_isValid( true )
  11. {
  12. for ( int i = 0; i < NTickTypes; i++ )
  13. d_ticks[i] = ticks[i];
  14. }
再看一下其实现值得借鉴的函数接口:

[cpp] view plain copy
  1. /*!
  2. Return a list of ticks
  3. \param type MinorTick, MediumTick or MajorTick
  4. */
  5. const QList<double> &QwtScaleDiv::ticks( int type ) const
  6. {
  7. if ( type >= 0 || type < NTickTypes ) // 防错性判断,OK!
  8. return d_ticks[type];
  9. static QList<double> noTicks;
  10. return noTicks;
  11. }
static QList noTicks; // 定义一个局部的静态变量,只初始化一次即可。如果在一个循环中调用ticks(),恰好输入的参数有误,则能大幅度提高效率。

4、QwtAbstractScaleDraw类
数据:

[cpp] view plain copy
  1. class QwtAbstractScaleDraw::PrivateData
  2. {
  3. public:
  4. PrivateData():
  5. spacing( 4.0 ),
  6. penWidth( 0 ),
  7. minExtent( 0.0 )
  8. {
  9. components = QwtAbstractScaleDraw::Backbone
  10. | QwtAbstractScaleDraw::Ticks
  11. | QwtAbstractScaleDraw::Labels;
  12. tickLength[QwtScaleDiv::MinorTick] = 4.0;
  13. tickLength[QwtScaleDiv::MediumTick] = 6.0;
  14. tickLength[QwtScaleDiv::MajorTick] = 8.0;
  15. }
  16. ScaleComponents components; // 标尺包含哪些部分
  17. QwtScaleMap map;
  18. QwtScaleDiv scldiv;
  19. double spacing;
  20. double tickLength[QwtScaleDiv::NTickTypes]; // 刻度线的长度
  21. int penWidth;
  22. double minExtent;
  23. QMap<double, QwtText> labelCache;// 标签缓存
  24. };
实现:
QwtAbstractScaleDraw类使用了模板方法模式【Template Method】,draw()方法定义了绘制标尺的基本框架:

[cpp] view plain copy
  1. /*!
  2. \brief Draw the scale
  3. \param painter The painter
  4. \param palette Palette, text color is used for the labels,
  5. foreground color for ticks and backbone
  6. */
  7. void QwtAbstractScaleDraw::draw( QPainter *painter,
  8. const QPalette& palette ) const
  9. {
  10. painter->save();
  11. QPen pen = painter->pen();
  12. pen.setWidth( d_data->penWidth );
  13. pen.setCosmetic( false );
  14. painter->setPen( pen );
  15. if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
  16. {
  17. painter->save();
  18. painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style
  19. const QList<double> &majorTicks =
  20. d_data->scldiv.ticks( QwtScaleDiv::MajorTick );
  21. for ( int i = 0; i < majorTicks.count(); i++ )
  22. {
  23. const double v = majorTicks[i];
  24. if ( d_data->scldiv.contains( v ) )
  25. drawLabel( painter, majorTicks[i] ); // 绘制标签,纯虚函数,具体的实现延迟到子类中
  26. }
  27. painter->restore();
  28. }
  29. if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
  30. {
  31. painter->save();
  32. QPen pen = painter->pen();
  33. pen.setColor( palette.color( QPalette::WindowText ) );
  34. pen.setCapStyle( Qt::FlatCap );
  35. painter->setPen( pen );
  36. for ( int tickType = QwtScaleDiv::MinorTick;
  37. tickType < QwtScaleDiv::NTickTypes; tickType++ )
  38. {
  39. const QList<double> &ticks = d_data->scldiv.ticks( tickType );
  40. for ( int i = 0; i < ticks.count(); i++ )
  41. {
  42. const double v = ticks[i];
  43. if ( d_data->scldiv.contains( v ) )
  44. drawTick( painter, v, d_data->tickLength[tickType] ); // 绘制刻度,纯虚函数,具体的实现延迟至子类中
  45. }
  46. }
  47. painter->restore();
  48. }
  49. if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
  50. {
  51. painter->save();
  52. QPen pen = painter->pen();
  53. pen.setColor( palette.color( QPalette::WindowText ) );
  54. pen.setCapStyle( Qt::FlatCap );
  55. painter->setPen( pen );
  56. drawBackbone( painter ); // 绘制标尺底线,纯虚函数,具体的实现延迟至子类中
  57. painter->restore();
  58. }
  59. painter->restore();
  60. }

参数设置接口:
[cpp] view plain copy
  1. void setScaleDiv( const QwtScaleDiv &s );
  2. const QwtScaleDiv& scaleDiv() const;
  3. void setTransformation( QwtScaleTransformation * );
  4. const QwtScaleMap &scaleMap() const;
  5. QwtScaleMap &scaleMap();
当然,也可以设置笔的宽度,刻度线的长度等属性显示不同风格的刻度。
5、QwtScaleDraw类
主要实现了QwtAbstractScaleDraw的四个纯虚函数,以及标尺的位置(原点)移动;标签旋转;刻度对齐;等功能。
6、QwtScaleWidget类
一个较好的接口命名示例代码:
[cpp] view plain copy
  1. void getMinBorderDist( int &start, int &end ) const; // 通过引用返回两个值
  2. void setMinBorderDist( int start, int end );
设置坐标转化和刻度划分:
[cpp] view plain copy
  1. void setScaleDiv( QwtScaleTransformation *, const QwtScaleDiv &sd );
  2. void setScaleDraw( QwtScaleDraw * );
  3. const QwtScaleDraw *scaleDraw() const;
  4. QwtScaleDraw *scaleDraw();
色标的使用:
[cpp] view plain copy
  1. void setColorMap( const QwtInterval &, QwtColorMap * );
  2. QwtInterval colorBarInterval() const;
  3. const QwtColorMap *colorMap() const;
7、最后再看标尺用到的一个“静态工具类”QwtScaleArithmetic:

[cpp] view plain copy
  1. /*!
  2. \brief Arithmetic including a tolerance
  3. */
  4. class QWT_EXPORT QwtScaleArithmetic
  5. {
  6. public:
  7. static double ceilEps( double value, double intervalSize );
  8. static double floorEps( double value, double intervalSize );
  9. static double divideEps( double interval, double steps );
  10. static double ceil125( double x );
  11. static double floor125( double x );
  12. };
这样分类定义的静态函数明显优于全局函数。

转载:http://blog.csdn.net/e5max/article/details/8850982

你可能感兴趣的:(Qt,qwt,标尺相关类)