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

一、简介

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

二、关系图

(1)三者间的关系

(2)坐标系统

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

(3)坐标映射

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

三、详解

1、运行图

2、解析

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

  1. #include <QGraphicsItem>
  2. #include <QObject>
  3. class Butterfly : public QObject, public QGraphicsItem
  4. {
  5.     Q_OBJECT
  6. public:
  7.     Butterfly();
  8.     void timerEvent(QTimerEvent *);
  9.     QRectF boundingRect() const;
  10. protected:
  11.     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
  12. private:
  13.     bool up;
  14.     QPixmap pix_up;
  15.     QPixmap pix_down;
  16.     qreal angle;
  17. };
  1. static const double PI = 3.14159265358979323846264338327950288419717;
  2. Butterfly::Butterfly()
  3. {
  4.     setFlag(QGraphicsItem::ItemIsMovable);
  5.     pix_up.load(“:/images/butterfly1.PNG”);
  6.     pix_down.load(“:/images/butterfly2.PNG”);
  7.     up = true;
  8.     startTimer(100);
  9. }
  10. QRectF Butterfly::boundingRect() const
  11. {
  12.     qreal adjust = 8;
  13.     return QRectF(-pix_up.width()/2-adjust,-pix_up.height()/2-adjust,
  14.                 pix_up.width()+adjust*2,pix_up.height()+2*adjust);
  15. }
  16. void Butterfly::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
  17. {
  18.     if(up)
  19.     {
  20.         painter->drawPixmap(boundingRect().topLeft(),pix_up);
  21.         up = !up;
  22.     }
  23.     else
  24.     {
  25.         painter->drawPixmap(boundingRect().topLeft(),pix_down);
  26.         up = !up;
  27.     }
  28. //    painter->setPen(Qt::NoPen);
  29. //    painter->setBrush(Qt::darkGray);
  30. //    painter->drawEllipse(-7,-7,40,40);
  31. //    painter->setPen(QPen(Qt::black,0));
  32. //    painter->setBrush(flash ? (Qt::red):(Qt::yellow));
  33. //    painter->drawEllipse(-10,-10,40,40);
  34. }
  35. void Butterfly::timerEvent(QTimerEvent *)
  36. {
  37.     // edge controll
  38.     qreal edgex = scene()->sceneRect().right()+boundingRect().width()/2;
  39.     qreal edgetop = scene()->sceneRect().top()+boundingRect().height()/2;
  40.     qreal edgebottom = scene()->sceneRect().bottom()+boundingRect().height()/2;
  41.     //qDebug() << scene()->itemsBoundingRect();
  42.     if (pos().x() >= edgex)
  43.         setPos(scene()->sceneRect().left(),pos().y());
  44.     if (pos().y() <= edgetop)
  45.         setPos(pos().x(),scene()->sceneRect().bottom());
  46.     if (pos().y() >= edgebottom)
  47.         setPos(pos().x(),scene()->sceneRect().top());
  48.     angle += (qrand()%10)/20.0;
  49.     qreal dx = fabs(sin(angle*PI)*10.0);
  50.     qreal dy = (qrand()%20)-10.0;
  51.     setPos(mapToParent(dx,dy));
  52.     update();
  53. }

分 析:在定时器的timeEvent()中对QGraphicsItem进行重画,重画paint()函数中飞舞的蝴蝶是由两幅图片组成,蝴蝶的移动边界做 一个限定,dx和dy是相对于蝴蝶的坐标系而言的,调用setPos函数时使用mapToParent()函数映射成场景的坐标。 setFlag(QGraphicsItem::ItemIsMovable);使蝴蝶可以通过鼠标移动。

(2)来回移动的星星

  1. class StarItem : public QGraphicsItem
  2. {
  3. public:
  4.     StarItem();
  5.     QRectF boundingRect() const;
  6.     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
  7. private:
  8.     QPixmap pix;
  9. };
  1. StarItem::StarItem()
  2. {
  3.     pix.load(“:/images/star.png”);
  4. }
  5. QRectF StarItem::boundingRect() const
  6. {
  7.     return QRectF(-pix.width()/2,-pix.height()/2,pix.width(),pix.height());
  8. }
  9. void
  10. StarItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
  11. {
  12.     painter->drawPixmap(boundingRect().topLeft(),pix);
  13. }
  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.     int y = (qrand()%400) – 200;
  10.     for (int i=0; i<400; i++)
  11.     {
  12.         anim->setPosAt(i/400.0, QPointF(i-200,y));
  13.     }
  14.     timeLine->start();
  15.     scene->addItem(star);
  16. }

分析:利用QGraphicsItemAnimation类和QTimeLine实现项目的动画效果(也可使用定时器QTimer结合重绘函数来实现)。

(3)简单正方形

  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);
赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏