Qwt源码解读之标尺相关类——日期时间标尺绘制类QwtDateScaleDraw

来源:互联网 发布:天刀好看少女捏脸数据 编辑:程序博客网 时间:2024/06/05 16:55

先看一看Qwt文档的说明:

A class for drawing datetime scales.

QwtDateScaleDraw displays values as datetime labels. The format of the labels depends on the alignment of the major tick labels.

The default format strings are:

Millisecond----------"hh:mm:ss:zzz\nddd dd MMM yyyy"
Second---------------"hh:mm:ss\nddd dd MMM yyyy"
Minute----------------"hh:mm\nddd dd MMM yyyy"
Hour------------------"hh:mm\nddd dd MMM yyyy"
Day-------------------"ddd dd MMM yyyy"
Week-----------------"Www yyyy"
Month----------------"MMM yyyy"
Year------------------"yyyy"
The format strings can be modified using setDateFormat() or individually for each tick label by overloading dateFormatOfDate(),
Usually QwtDateScaleDraw is used in combination with QwtDateScaleEngine, that calculates scales for datetime intervals.
See Also
QwtDateScaleEngine, QwtPlot::setAxisScaleDraw()

QWT是用于绘制科学图形的Qt库。使用QwtPlot类可以绘制各种类型的坐标曲线图。对于绝大部分坐标图,标尺都是以普通的数值为单位的,如1,2,3...100等。但是有时候我们可能需要以时间或日期为单位。Qwt提供了一个这样的标尺类QwtDateScaleDraw。

QwtPlot默认会创建两个Scale对象,即水平标尺(xBottom)和垂直标尺(yLeft)。不过QwtPlot提供了一些方法,允许开发人员将默认的Scale对象替换成定制的标尺,比如QwtDateScaleDraw对象(以日期时间为单位的标尺)。

替换QwtPlot对象中的默认Scale对象的代码如下:

QwtDateScaleDraw *timeScale = new QwtDateScaleDraw(Qt::LocalTime);QwtPlot *plot = new QwtPlot();plot->setAxisScaleDraw(QwtPlot::xBottom, timeScale);delete plot;// 注意:当删除plot对象时,timeScale也会被自动删除。
其中,Qwt帮助文档中setAxisScaleDraw()方法的原型和解释如下:
void QwtPlot::setAxisScaleDraw(int axisId, QwtScaleDraw * scaleDraw )
By passing scaleDraw it is possible to extend QwtScaleDraw functionality and let it take place in QwtPlot. Please note that scaleDraw has to be created with new and will be deleted by the corresponding QwtScale member ( like a child object ).

    翻译过来是说:通过传入scaleDraw参数,可以替代QwtPlot中的QwtScaleDraw,并扩展其功能。请注意,scaleDraw必须使用new关键字创建,作为相关的QwtScale成员,会被像子对象一样删除(笔者注:Qt会自动delete子对象)。

    这就是在上述代码中,只需要delete plot,而不用再delete timeScale了。

    QwtDateScaleDraw允许开发人员对时间刻度的显示方式进行设置,下面的代码将设置在毫秒级别以“Sec 秒:毫秒”的方式显示,在秒及其以上级别以“时:分:秒\n年-月-日”的方式进行显示,其中“\n”表示换行。

QString *scaleFormat;scaleFormat = new QString("Sec ss:zzz");timeScale->setDateFormat(QwtDate::Millisecond, *scaleFormat);delete scaleFormat;scaleFormat = new QString("hh:mm:ss\nyy-MM-dd");timeScale->setDateFormat(QwtDate::Second, *scaleFormat);delete scaleFormat;
最终显示效果如下:

类继承关系

如下图所示:


类定义:

class QWT_EXPORT QwtDateScaleDraw: public QwtScaleDraw{public:    QwtDateScaleDraw( Qt::TimeSpec = Qt::LocalTime );// 构造函数    virtual ~QwtDateScaleDraw();// 析构函数    void setDateFormat( QwtDate::IntervalType, const QString & );//设置显示毫秒、秒、分、时、日、月、年等时的格式。    QString dateFormat( QwtDate::IntervalType ) const;// 获取日期时间格式    void setTimeSpec( Qt::TimeSpec );// 设置时间规范,可取值LocalTime、UTC、OffsetFromUTC、TimeZone    Qt::TimeSpec timeSpec() const;    void setUtcOffset( int seconds );    int utcOffset() const;    void setWeek0Type( QwtDate::Week0Type );    QwtDate::Week0Type week0Type() const;    virtual QwtText label( double ) const;    QDateTime toDateTime( double ) const;protected:    virtual QwtDate::IntervalType         intervalType( const QwtScaleDiv & ) const;    virtual QString dateFormatOfDate( const QDateTime &,        QwtDate::IntervalType ) const;private:    class PrivateData;    PrivateData *d_data;};
其中私有数据PrivateData定义:
class QwtDateScaleDraw::PrivateData{public:    PrivateData( Qt::TimeSpec spec ):        timeSpec( spec ),        utcOffset( 0 ),        week0Type( QwtDate::FirstThursday )    {        dateFormats[ QwtDate::Millisecond ] = "hh:mm:ss:zzz\nddd dd MMM yyyy";        dateFormats[ QwtDate::Second ] = "hh:mm:ss\nddd dd MMM yyyy";        dateFormats[ QwtDate::Minute ] = "hh:mm\nddd dd MMM yyyy";        dateFormats[ QwtDate::Hour ] = "hh:mm\nddd dd MMM yyyy";        dateFormats[ QwtDate::Day ] = "ddd dd MMM yyyy";        dateFormats[ QwtDate::Week ] = "Www yyyy";        dateFormats[ QwtDate::Month ] = "MMM yyyy";        dateFormats[ QwtDate::Year ] = "yyyy";    }    Qt::TimeSpec timeSpec;// 时间规范,可取值LocalTime,UTC,OffsetFromUTC,TimeZone    int utcOffset;    QwtDate::Week0Type week0Type;// 表示一年中的第一个星期从哪天开始,是从第一个星期四开始,还是从一月一日开始    QString dateFormats[ QwtDate::Year + 1 ];};

枚举类型

    enum TimeSpec {        LocalTime,        UTC,        OffsetFromUTC,        TimeZone    };
    /*!       Classification of an time interval      Time intervals needs to be classified to decide how to      align and divide it.     */    enum IntervalType    {        //! The interval is related to milliseconds        Millisecond,        //! The interval is related to seconds        Second,        //! The interval is related to minutes        Minute,        //! The interval is related to hours        Hour,        //! The interval is related to days        Day,        //! The interval is related to weeks        Week,        //! The interval is related to months        Month,        //! The interval is related to years        Year    };
    /*!        How to identify the first week of year differs between       countries.      */    enum Week0Type    {        /*!           According to ISO 8601 the first week of a year is defined           as "the week with the year's first Thursday in it".           FirstThursday corresponds to the numbering that is           implemented in QDate::weekNumber().        */        FirstThursday,        /*!            "The week with January 1.1 in it."                       In the U.S. this definition is more common than            FirstThursday.        */        FirstDay    };
/*!  Set the offset in seconds from Coordinated Universal Time  \param seconds Offset in seconds  \note The offset has no effect beside for the time specification        Qt::OffsetFromUTC.  \sa QDate::utcOffset(), setTimeSpec(), toDateTime() */void QwtDateScaleDraw::setUtcOffset( int seconds ){    d_data->utcOffset = seconds;}
设置与协调世界时的偏移。
/*!  Sets how to identify the first week of a year.  \param week0Type Mode how to identify the first week of a year  \sa week0Type().  \note week0Type has no effect beside for intervals classified as        QwtDate::Week.  */void QwtDateScaleDraw::setWeek0Type( QwtDate::Week0Type week0Type ){    d_data->week0Type = week0Type;}
设置怎样识别一年的第一个星期从哪天开始,是从第一个星期四开始还是从一月一日开始。
/*!  Set the default format string for an datetime interval type  \param intervalType Interval type  \param format Default format string  \sa dateFormat(), dateFormatOfDate(), QwtDate::toString() */void QwtDateScaleDraw::setDateFormat(     QwtDate::IntervalType intervalType, const QString &format ){    if ( intervalType >= QwtDate::Millisecond &&         intervalType <= QwtDate::Year )    {// 首先检查输入参数intervalType的合法性        d_data->dateFormats[ intervalType ] = format;    }}

设置日期时间格式。

/*!  Format string for the representation of a datetime  dateFormatOfDate() is intended to be overloaded for  situations, where formats are individual for specific  datetime values.  The default setting ignores dateTime and return  the default format for the interval type.  \param dateTime Datetime value  \param intervalType Interval type  \return Format string  \sa setDateFormat(), QwtDate::toString() */QString QwtDateScaleDraw::dateFormatOfDate( const QDateTime &dateTime,    QwtDate::IntervalType intervalType ) const{    Q_UNUSED( dateTime )    if ( intervalType >= QwtDate::Millisecond &&         intervalType <= QwtDate::Year )    {        return d_data->dateFormats[ intervalType ];    }    return d_data->dateFormats[ QwtDate::Second ];}
/*!  \brief Convert a value into its representing label  The value is converted to a datetime value using toDateTime()  and converted to a plain text using QwtDate::toString().  \param value Value  \return Label string.  \sa dateFormatOfDate()*/QwtText QwtDateScaleDraw::label( double value ) const{    const QDateTime dt = toDateTime( value );    const QString fmt = dateFormatOfDate(         dt, intervalType( scaleDiv() ) );    return QwtDate::toString( dt, fmt, d_data->week0Type );}
将一个double值value按照指定的格式转换成(表示日期时间的)字符串。
/*!  Find the less detailed datetime unit, where no rounding  errors happen.  \param scaleDiv Scale division  \return Interval type  \sa dateFormatOfDate() */QwtDate::IntervalType QwtDateScaleDraw::intervalType(     const QwtScaleDiv &scaleDiv ) const{    int intvType = QwtDate::Year;    bool alignedToWeeks = true;    const QList<double> ticks = scaleDiv.ticks( QwtScaleDiv::MajorTick );    for ( int i = 0; i < ticks.size(); i++ )    {        const QDateTime dt = toDateTime( ticks[i] );        for ( int j = QwtDate::Second; j <= intvType; j++ )        {            const QDateTime dt0 = QwtDate::floor( dt,                 static_cast<QwtDate::IntervalType>( j ) );            if ( dt0 != dt )            {                if ( j == QwtDate::Week )                {                    alignedToWeeks = false;                }                else                {                    intvType = j - 1;                    break;                }            }        }        if ( intvType == QwtDate::Millisecond )            break;    }    if ( intvType == QwtDate::Week && !alignedToWeeks )        intvType = QwtDate::Day;    return static_cast<QwtDate::IntervalType>( intvType );}
返回详细信息最少,且没有舍入误差的日期时间单位。
/*!  Translate a double value into a QDateTime object.  \return QDateTime object initialized with timeSpec() and utcOffset().  \sa timeSpec(), utcOffset(), QwtDate::toDateTime() */QDateTime QwtDateScaleDraw::toDateTime( double value ) const{    QDateTime dt = QwtDate::toDateTime( value, d_data->timeSpec );    if ( d_data->timeSpec == Qt::OffsetFromUTC )    {        dt = dt.addSecs( d_data->utcOffset );        dt.setUtcOffset( d_data->utcOffset );    }    return dt;}
将一个double值value转换成QDateTime对象。
0 0