Qwt源碼解讀之尺規相關類

來源:互聯網
上載者:User

  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 類提供了以下介面:尺規座標值與繪製裝置座標值之間的轉化。

    virtual double xForm( double s, double s1, double s2,        double p1, double p2 ) const;    virtual double invXForm( double p, double p1, double p2,        double s1, double s2 ) const;

由于禁用了拷貝建構函式和拷貝賦值操作符函數,因此還提供了複製函數:

//! Create a clone of the transformationQwtScaleTransformation *QwtScaleTransformation::copy() const{    return new QwtScaleTransformation( d_type );}

2、QwtScaleMap類
這裡看一下QwtScaleMap的拷貝建構函式和拷貝賦值操作符函數,協助理解上面 QwtScaleTransformation類的copy()函數。

//! Copy constructorQwtScaleMap::QwtScaleMap( const QwtScaleMap& other ):    d_s1( other.d_s1 ),    d_s2( other.d_s2 ),    d_p1( other.d_p1 ),    d_p2( other.d_p2 ),    d_cnv( other.d_cnv ){    d_transformation = other.d_transformation->copy();}//! Assignment operatorQwtScaleMap &QwtScaleMap::operator=( const QwtScaleMap & other ){    d_s1 = other.d_s1;    d_s2 = other.d_s2;    d_p1 = other.d_p1;    d_p2 = other.d_p2;    d_cnv = other.d_cnv;    delete d_transformation;    d_transformation = other.d_transformation->copy();    return *this;}//! Copy constructorQwtScaleMap::QwtScaleMap( const QwtScaleMap& other ):    d_s1( other.d_s1 ),    d_s2( other.d_s2 ),    d_p1( other.d_p1 ),    d_p2( other.d_p2 ),    d_cnv( other.d_cnv ){    d_transformation = other.d_transformation->copy();}//! Assignment operatorQwtScaleMap &QwtScaleMap::operator=( const QwtScaleMap & other ){    d_s1 = other.d_s1;    d_s2 = other.d_s2;    d_p1 = other.d_p1;    d_p2 = other.d_p2;    d_cnv = other.d_cnv;    delete d_transformation;    d_transformation = other.d_transformation->copy();    return *this;}

然後,QwtScaleMap的參數設定介面和完成座標系統之間值轉化的功能函數:

    void setPaintInterval( double p1, double p2 );    void setScaleInterval( double s1, double s2 );    double transform( double s ) const;    double invTransform( double p ) const;

3、QwtScaleDiv類
      QwtScaleDiv類共有3個建構函式,不帶參數的預設建構函式建立一個“無效的”刻度劃分執行個體。我們看具有兩個參數的建構函式,就能明白了QwtScaleDiv的基本屬性特徵。

/*!  Construct QwtScaleDiv instance.  \param interval Interval  \param ticks List of major, medium and minor ticks*/QwtScaleDiv::QwtScaleDiv( const QwtInterval &interval,        QList<double> ticks[NTickTypes] ):    d_lowerBound( interval.minValue() ),    d_upperBound( interval.maxValue() ),    d_isValid( true ){    for ( int i = 0; i < NTickTypes; i++ )        d_ticks[i] = ticks[i];}

再看一下其實現值得借鑒的函數介面:

/*!   Return a list of ticks   \param type MinorTick, MediumTick or MajorTick*/const QList<double> &QwtScaleDiv::ticks( int type ) const{    if ( type >= 0 || type < NTickTypes ) // 防錯性判斷,OK!        return d_ticks[type];    static QList<double> noTicks;     return noTicks;}

static QList<double> noTicks;  // 定義一個局部的靜態變數,只初始化一次即可。如果在一個迴圈中調用ticks(),恰好輸入的參數有誤,則能大幅度提高效率。

4、QwtAbstractScaleDraw類
資料:

class QwtAbstractScaleDraw::PrivateData{public:    PrivateData():        spacing( 4.0 ),        penWidth( 0 ),        minExtent( 0.0 )    {        components = QwtAbstractScaleDraw::Backbone             | QwtAbstractScaleDraw::Ticks             | QwtAbstractScaleDraw::Labels;        tickLength[QwtScaleDiv::MinorTick] = 4.0;        tickLength[QwtScaleDiv::MediumTick] = 6.0;        tickLength[QwtScaleDiv::MajorTick] = 8.0;    }    ScaleComponents components; // 尺規包含哪些部分    QwtScaleMap map;    QwtScaleDiv scldiv;    double spacing;    double tickLength[QwtScaleDiv::NTickTypes]; // 刻度標記的長度    int penWidth;    double minExtent;    QMap<double, QwtText> labelCache;// 標籤緩衝};

實現:
QwtAbstractScaleDraw類使用了模板方法模式【Template Method】,draw()方法定義了繪製尺規的基本架構:

/*!  \brief Draw the scale  \param painter    The painter  \param palette    Palette, text color is used for the labels,                    foreground color for ticks and backbone*/void QwtAbstractScaleDraw::draw( QPainter *painter,    const QPalette& palette ) const{    painter->save();    QPen pen = painter->pen();    pen.setWidth( d_data->penWidth );    pen.setCosmetic( false );    painter->setPen( pen );    if ( hasComponent( QwtAbstractScaleDraw::Labels ) )    {        painter->save();        painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style        const QList<double> &majorTicks =            d_data->scldiv.ticks( QwtScaleDiv::MajorTick );        for ( int i = 0; i < majorTicks.count(); i++ )        {            const double v = majorTicks[i];            if ( d_data->scldiv.contains( v ) )                drawLabel( painter, majorTicks[i] ); // 繪製標籤,純虛函數,具體的實現延遲到子類中        }        painter->restore();    }    if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )    {        painter->save();        QPen pen = painter->pen();        pen.setColor( palette.color( QPalette::WindowText ) );        pen.setCapStyle( Qt::FlatCap );        painter->setPen( pen );        for ( int tickType = QwtScaleDiv::MinorTick;            tickType < QwtScaleDiv::NTickTypes; tickType++ )        {            const QList<double> &ticks = d_data->scldiv.ticks( tickType );            for ( int i = 0; i < ticks.count(); i++ )            {                const double v = ticks[i];                if ( d_data->scldiv.contains( v ) )                    drawTick( painter, v, d_data->tickLength[tickType] ); // 繪製刻度,純虛函數,具體的實現延遲至子類中            }        }        painter->restore();    }    if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )    {        painter->save();        QPen pen = painter->pen();        pen.setColor( palette.color( QPalette::WindowText ) );        pen.setCapStyle( Qt::FlatCap );        painter->setPen( pen );        drawBackbone( painter );  // 繪製尺規底線,純虛函數,具體的實現延遲至子類中        painter->restore();    }    painter->restore();}

參數設定介面:

    void setScaleDiv( const QwtScaleDiv &s );    const QwtScaleDiv& scaleDiv() const;    void setTransformation( QwtScaleTransformation * );    const QwtScaleMap &scaleMap() const;    QwtScaleMap &scaleMap();

當然,也可以設定筆的寬度,刻度標記的長度等屬性顯示不同風格的刻度。
5、QwtScaleDraw類
主要實現了QwtAbstractScaleDraw的四個純虛函數,以及尺規的位置(原點)移動;標籤旋轉;刻度對齊;等功能。
6、QwtScaleWidget類
一個較好的介面命名範例程式碼:

    void getMinBorderDist( int &start, int &end ) const; // 通過引用返回兩個值    void setMinBorderDist( int start, int end );

設定座標轉化和刻度劃分:

    void setScaleDiv( QwtScaleTransformation *, const QwtScaleDiv &sd );    void setScaleDraw( QwtScaleDraw * );    const QwtScaleDraw *scaleDraw() const;    QwtScaleDraw *scaleDraw();

色標的使用:

    void setColorMap( const QwtInterval &, QwtColorMap * );    QwtInterval colorBarInterval() const;    const QwtColorMap *colorMap() const;

7、最後再看尺規用到的一個“靜態工具類”QwtScaleArithmetic:

/*!  \brief Arithmetic including a tolerance*/class QWT_EXPORT QwtScaleArithmetic{public:    static double ceilEps( double value, double intervalSize );    static double floorEps( double value, double intervalSize );    static double divideEps( double interval, double steps );    static double ceil125( double x );    static double floor125( double x );};

這樣分類定義的靜態函數明顯優於全域函數。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.