Qt浅谈之十七:飞舞的蝴蝶(GraphicsView框架)

来源:互联网 发布:mysql和oracle语法区别 编辑:程序博客网 时间:2024/04/28 20:14

一、简介

       GraphicsView框架结构主要包含三个主要的类QGraphicsScene(容器)、QGraphicsView(视图)、QGraphicsItem(图形项)。QGraphicsScene本身不可见必须通过与之相连的QGraphicsView视口类来显示及与外界进行互操作,主要提供项目的操作接口、传递事件和管理各个项目状态;QGraphicsView提供一个可视的窗口,用于显示场景中的项目,一个场景中可以有多个视口;QGraphicsItem是场景中各个项目的基础类。

二、关系图

(1)三者间的关系


(2)坐标系统

QGraphicsScene坐标系是以中心为原点(0,0),QGraphicsView继承自QWidget以窗口的左上角作为自己坐标系的原点,而QGraphicsItem则有自己的坐标系其paint()函数重画时以此坐标系为基准。

(3)坐标映射

三个坐标系之间的相互转换函数及图形项与图形项之间的转换函数。

三、详解

1、运行图


2、解析

(1)利用定时器实现QGraphicsItem不停上下飞舞的蝴蝶的动画效果

[cpp] view plain copy
  1. #include <QGraphicsItem>  
  2. #include <QObject>  
  3.   
  4. class Butterfly : public QObject, public QGraphicsItem  
  5. {  
  6.     Q_OBJECT  
  7. public:  
  8.     Butterfly();  
  9.     void timerEvent(QTimerEvent *);  
  10.     QRectF boundingRect() const;  
  11.      
  12. protected:  
  13.     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);  
  14.   
  15.       
  16. private:  
  17.     bool up;  
  18.     QPixmap pix_up;  
  19.     QPixmap pix_down;   
  20.       
  21.     qreal angle;  
  22.   
  23. };  
[cpp] view plain copy
  1. static const double PI = 3.14159265358979323846264338327950288419717;  
  2.   
  3. Butterfly::Butterfly()  
  4. {   
  5.     setFlag(QGraphicsItem::ItemIsMovable);  
  6.   
  7.     pix_up.load(":/images/butterfly1.PNG");  
  8.     pix_down.load(":/images/butterfly2.PNG");  
  9.     up = true;  
  10.     startTimer(100);  
  11. }  
  12.   
  13. QRectF Butterfly::boundingRect() const  
  14. {  
  15.     qreal adjust = 8;  
  16.     return QRectF(-pix_up.width()/2-adjust,-pix_up.height()/2-adjust,  
  17.                 pix_up.width()+adjust*2,pix_up.height()+2*adjust);  
  18. }  
  19.   
  20. void Butterfly::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)  
  21. {  
  22.     if(up)  
  23.     {  
  24.         painter->drawPixmap(boundingRect().topLeft(),pix_up);  
  25.         up = !up;  
  26.     }  
  27.     else  
  28.     {  
  29.         painter->drawPixmap(boundingRect().topLeft(),pix_down);  
  30.         up = !up;  
  31.     }  
  32. //    painter->setPen(Qt::NoPen);  
  33. //    painter->setBrush(Qt::darkGray);  
  34. //    painter->drawEllipse(-7,-7,40,40);  
  35.   
  36. //    painter->setPen(QPen(Qt::black,0));  
  37. //    painter->setBrush(flash ? (Qt::red):(Qt::yellow));  
  38. //    painter->drawEllipse(-10,-10,40,40);  
  39.           
  40. }  
  41.   
  42. void Butterfly::timerEvent(QTimerEvent *)  
  43. {  
  44.     // edge controll  
  45.     qreal edgex = scene()->sceneRect().right()+boundingRect().width()/2;  
  46.     qreal edgetop = scene()->sceneRect().top()+boundingRect().height()/2;  
  47.     qreal edgebottom = scene()->sceneRect().bottom()+boundingRect().height()/2;  
  48.     //qDebug() << scene()->itemsBoundingRect();  
  49.     if (pos().x() >= edgex)  
  50.         setPos(scene()->sceneRect().left(),pos().y());  
  51.     if (pos().y() <= edgetop)  
  52.         setPos(pos().x(),scene()->sceneRect().bottom());  
  53.     if (pos().y() >= edgebottom)  
  54.         setPos(pos().x(),scene()->sceneRect().top());  
  55.       
  56.     angle += (qrand()%10)/20.0;  
  57.     qreal dx = fabs(sin(angle*PI)*10.0);  
  58.     qreal dy = (qrand()%20)-10.0;  
  59.       
  60.     setPos(mapToParent(dx,dy));  
  61.     update();  
  62. }  
分析:在定时器的timeEvent()中对QGraphicsItem进行重画,重画paint()函数中飞舞的蝴蝶是由两幅图片组成,蝴蝶的移动边界做一个限定,dx和dy是相对于蝴蝶的坐标系而言的,调用setPos函数时使用mapToParent()函数映射成场景的坐标。setFlag(QGraphicsItem::ItemIsMovable);使蝴蝶可以通过鼠标移动。

(2)来回移动的星星

[cpp] view plain copy
  1. class StarItem : public QGraphicsItem  
  2. {  
  3. public:  
  4.     StarItem();  
  5.   
  6.     QRectF boundingRect() const;  
  7.     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);  
  8.   
  9. private:  
  10.     QPixmap pix;  
  11. };  
[cpp] view plain copy
  1. StarItem::StarItem()  
  2. {  
  3.     pix.load(":/images/star.png");  
  4. }  
  5.   
  6. QRectF StarItem::boundingRect() const  
  7. {  
  8.     return QRectF(-pix.width()/2,-pix.height()/2,pix.width(),pix.height());  
  9. }  
  10.   
  11. void  
  12. StarItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)  
  13. {  
  14.     painter->drawPixmap(boundingRect().topLeft(),pix);  
  15. }  
[cpp] view plain copy
  1. {  
  2.     StarItem *star = new StarItem;  
  3.     QGraphicsItemAnimation *anim = new QGraphicsItemAnimation;  
  4.     anim->setItem(star);  
  5.     QTimeLine *timeLine = new QTimeLine(4000);  
  6.     timeLine->setCurveShape(QTimeLine::SineCurve);  
  7.     timeLine->setLoopCount(0);  
  8.     anim->setTimeLine(timeLine);  
  9.   
  10.     int y = (qrand()%400) - 200;  
  11.     for (int i=0; i<400; i++)  
  12.     {  
  13.         anim->setPosAt(i/400.0, QPointF(i-200,y));  
  14.     }  
  15.     timeLine->start();  
  16.     scene->addItem(star);  
  17. }  
分析:利用QGraphicsItemAnimation类和QTimeLine实现项目的动画效果(也可使用定时器QTimer结合重绘函数来实现)。

(3)简单正方形

[cpp] view plain copy
  1. {  
  2.     QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0,0,60,60));  
  3.     QPen pen;  
  4.     pen.setWidth(3);  
  5.     pen.setColor(QColor(qrand()%256,qrand()%256,qrand()%256));  
  6.     item->setPen(pen);  
  7.     item->setBrush(QColor(qrand()%256,qrand()%256,qrand()%256));  
  8.     item->setFlag(QGraphicsItem::ItemIsMovable);  
  9.     scene->addItem(item);  
  10.     //item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);  
  11.     item->setPos(-200, -200);  
  12. }   

分析:利用继承QGraphicsItem的类QGraphicsRectItem添加一个正方形的图形项。



http://blog.csdn.net/taiyang1987912/article/details/38681969