0
点赞
收藏
分享

微信扫一扫

QWT官方例子--animation

天涯学馆 2022-02-25 阅读 36
qtqwt

文章目录


版本:qwt-6.1.3


一、运行效果

在这里插入图片描述


二、工程结构

在这里插入图片描述

在这里插入图片描述

本工程结构很简单,定义了继承自QwtPlot的Plot类,定义了一个继承自QwtPlotCurve的虚基类Curve,并由虚基类Curve派生出了四个类,分别是:Curve1、Curve2、Curve3、Curve4


三、代码分析

main.cpp

#include <qapplication.h>
#include "plot.h"

#ifndef QWT_NO_OPENGL
#define USE_OPENGL 1
#endif

#if USE_OPENGL
#include <qgl.h>
#include <qwt_plot_glcanvas.h>
#else
#include <qwt_plot_canvas.h>
#endif

int main ( int argc, char **argv )
{
#if USE_OPENGL
#if QT_VERSION >= 0x040600 && QT_VERSION < 0x050000
    // on my box QPaintEngine::OpenGL2 has serious problems, f.e:
    // the lines of a simple drawRect are wrong.

    QGL::setPreferredPaintEngine( QPaintEngine::OpenGL );
#endif
#endif

    QApplication a( argc, argv );

    Plot plot;  //创建视窗

#if USE_OPENGL
    QwtPlotGLCanvas *canvas = new QwtPlotGLCanvas();    //实例化画布
    canvas->setFrameStyle( QwtPlotGLCanvas::NoFrame );
#else
    QwtPlotCanvas *canvas = new QwtPlotCanvas();
    canvas->setFrameStyle( QFrame::NoFrame );
    canvas->setPaintAttribute( QwtPlotCanvas::BackingStore, false );
#endif

    plot.setCanvas( canvas );   //视窗设置画布
    plot.setCanvasBackground( QColor( 30, 30, 50 ) );   //视窗画布设置背景颜色

    plot.resize( 400, 400 );
    plot.show();

    return a.exec();
}

plot.h

#include <qwt_plot.h>
#include <qdatetime.h>

class Curve;

class Plot: public QwtPlot
{
public:
    Plot( QWidget * = NULL);

protected:
    virtual void timerEvent( QTimerEvent * );   //定时器事件

private:
    void updateCurves();

    enum { CurveCount = 4 };
    Curve *d_curves[CurveCount];    //曲线对象数组

    QTime d_time;   //计时器
};

plot.cpp

#include <qapplication.h>
#include <qwt_math.h>
#include <qwt_symbol.h>
#include <qwt_curve_fitter.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_layout.h>
#include <qevent.h>
#include "plot.h"

class Curve: public QwtPlotCurve
{
public:
    void setTransformation( const QTransform &transform )
    {
        d_transform = transform;
    }

    virtual void updateSamples( double phase )
    {
        setSamples( d_transform.map( points( phase ) ) );
    }

private:
    virtual QPolygonF points( double phase ) const = 0; //纯虚函数,点集接口

private:
    QTransform d_transform;
};

class Curve1: public Curve
{
public:
    Curve1()
    {
        //设置曲线样式
        setPen( QColor( 150, 150, 200 ), 2 );
        setStyle( QwtPlotCurve::Lines );

        //QwtCurveFitter在绘制之前尝试对曲线进行插值/平滑
        QwtSplineCurveFitter *curveFitter = new QwtSplineCurveFitter();
        curveFitter->setSplineSize( 150 );
        setCurveFitter( curveFitter );

        setCurveAttribute( QwtPlotCurve::Fitted, true );    //设置曲线属性

        //设置样本点标志
        QwtSymbol *symbol = new QwtSymbol( QwtSymbol::XCross );
        symbol->setPen( Qt::yellow );
        symbol->setSize( 7 );

        setSymbol( symbol );

        //设置坐标系转换
        QTransform transform;
        transform.scale( 1.5, 1.0 );
        transform.translate( 1.5, 3.0 );

        setTransformation( transform );
    }

    virtual QPolygonF points( double phase ) const
    {
        QPolygonF points;

        const int numSamples = 15;
        for ( int i = 0; i < numSamples; i++ )
        {
            const double v = 6.28 * double( i ) / double( numSamples - 1 );
            points += QPointF( qSin( v - phase ), v );
        }

        return points;
    }
};

class Curve2: public Curve
{
public:
    Curve2()
    {
        setStyle( QwtPlotCurve::Sticks );
        setPen( QColor( 200, 150, 50 ) );

        setSymbol( new QwtSymbol( QwtSymbol::Ellipse,
            QColor( Qt::gray ), QColor( Qt::yellow ), QSize( 5, 5 ) ) );
    }

private:
    virtual QPolygonF points( double phase ) const
    {
        QPolygonF points;

        const int numSamples = 50;
        for ( int i = 0; i < numSamples; i++ )
        {
            const double v = 10.0 * i / double( numSamples - 1 );
            points += QPointF( v, qCos( 3.0 * ( v + phase ) ) );
        }

        return points;
    }
};

class Curve3: public Curve
{       
public: 
    Curve3()
    {
        setStyle( QwtPlotCurve::Lines );
        setPen( QColor( 100, 200, 150 ), 2 );

        QwtSplineCurveFitter* curveFitter = new QwtSplineCurveFitter();
        curveFitter->setFitMode( QwtSplineCurveFitter::ParametricSpline );
        curveFitter->setSplineSize( 200 );
        setCurveFitter( curveFitter );

        setCurveAttribute( QwtPlotCurve::Fitted, true );

        // somewhere in the top right corner
        QTransform transform;
        transform.translate( 7.0, 7.5 );
        transform.scale( 2.0, 2.0 );

        setTransformation( transform );
    }   

private:
    virtual QPolygonF points( double phase ) const
    {
        QPolygonF points;

        const int numSamples = 9;
        for ( int i = 0; i < numSamples; i++ )
        {
            const double v = i * 2.0 * M_PI / ( numSamples - 1 );
            points += QPointF( qSin( v - phase ), qCos( 3.0 * ( v + phase ) ) );
        }

        return points;
    }
};  

class Curve4: public Curve
{       
public: 
    Curve4()
    {
        setStyle( QwtPlotCurve::Lines );
        setPen( Qt::red, 2 );

        initSamples();

        // somewhere in the center
        QTransform transform;
        transform.translate( 7.0, 3.0 );
        transform.scale( 1.5, 1.5 );

        setTransformation( transform );
    }   

private:
    virtual QPolygonF points( double phase ) const
    {
        const double speed = 0.05;

        const double s = speed * qSin( phase );
        const double c = qSqrt( 1.0 - s * s );

        for ( int i = 0; i < d_points.size(); i++ )
        {
            const QPointF p = d_points[i];

            const double u = p.x();
            const double v = p.y();

            d_points[i].setX( u * c - v * s );
            d_points[i].setY( v * c + u * s );
        }

        return d_points;
    }

    void initSamples()
    {
        const int numSamples = 15;

        for ( int i = 0; i < numSamples; i++ )
        {
            const double angle = i * ( 2.0 * M_PI / ( numSamples - 1 ) );

            QPointF p( qCos( angle ), qSin( angle ) );
            if ( i % 2 )
                p *= 0.4;
            
            d_points += p;
        }
    }

private:
    mutable QPolygonF d_points;
};  

Plot::Plot( QWidget *parent ):
    QwtPlot( parent)
{
    setAutoReplot( false ); //设置画布自动重绘

    setTitle( "Animated Curves" );  //设置窗口标题

    //隐藏所有坐标轴
    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
        enableAxis( axis, false );

    plotLayout()->setCanvasMargin( 10 ); //设置画布外边距为10

    d_curves[0] = new Curve1(); //初始化曲线对象
    d_curves[1] = new Curve2();
    d_curves[2] = new Curve3();
    d_curves[3] = new Curve4();

    updateCurves(); //更新曲线

    for ( int i = 0; i < CurveCount; i++ )  //将曲线贴附到画布上
        d_curves[i]->attach( this );

    d_time.start();
    ( void )startTimer( 40 );   //启动定时器,40ms
}

void Plot::timerEvent( QTimerEvent * )
{
    updateCurves();
    replot();
}

void Plot::updateCurves()
{
    const double speed = 2 * M_PI / 25000.0; // 每25秒一个周期

    const double phase = d_time.elapsed() * speed;
    for ( int i = 0; i < CurveCount; i++ )
        d_curves[i]->updateSamples( phase );
}


四、附加知识点

1、virtual void timerEvent( QTimerEvent * );

  • timerEvent事件可以方便的让对象定时的做某些事情;

  • timerEvent是QObject所内置的事件,所有继承自QObject的类都可以使用;

  • int startTimer(delaytime); 产生timerEvent,返回该对象的这个定时器Id号;

  • killTimer(timerId);挺尸该对象的ID号为timerId的计时器;

  • 一个对象可以有多个计时器,可通过e->timerId()来区分哪个timer触发了事件,例如;

class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
protected:
    void timerEvent(QTimerEvent* event);
 
private:
    Ui::MainWindow *ui;
    int id1;
    int id2;
    int id3;
};

//============================================================

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    id1 = startTimer(1000);	//开启一个1秒定时器,返回其ID
    id2 = startTimer(1500);	//开启一个1.5秒定时器,返回其ID
    id3 = startTimer(2200);	//开启一个2秒定时器,返回其ID
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
void MainWindow::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == id1) {
        qDebug()<<"timer1";
    }else if(event->timerId() == id2) {
        qDebug()<<"timer2";
    }else{
        qDebug()<<"timer3";
    }
}

2、QTime计时类

  • start():计数开始;
  • restart():计时重新开始,并返回自上次调用start()restart()以来经过的毫秒数;
  • elapsed():计时结束,并返回自上次调用

3、QTransform
QTransform是Qt中推荐的转换类,转换指定如何平移、缩放、剪切、旋转或者投影坐标系,通常在渲染图形时使用。

QTransform对象包含一个3*3的矩阵,如下:
在这里插入图片描述

  • m31(dx)和m32(dy)指定水平和垂直平移;
  • m11和m22元素指定水平和垂直缩放;
  • m21和m12元素指定水平和垂直剪切;
  • m13和m23元素指定水平和垂直投影,m33作为附加投影因子;

QTranform如何通过矩阵运算实现各种转换,可以参考这篇文章:Qt坐标系统之坐标变换矩阵(QTransform类)

常用函数:

  • QTransform& translate(qreal dx, qreal dy):沿x轴移动坐标系dx,并沿y轴移动dy,并返回对矩阵的引用;
  • QTransform& scale(qreal sx, qreal sy):按sx水平和sy垂直缩放坐标系,并返回对矩阵的引用;
  • QTransform& rotate(qreal angle, Qt::Axis axis = Qt::ZAxis):围绕指定的轴逆时针旋转坐标系,并返回对矩阵的引用;
  • QTransform& shear(qreal sh, qreal sv):水平剪切水平轴,垂直剪切水平轴sv,并返回对矩阵的引用;
举报

相关推荐

0 条评论