飞舞的蝴蝶(GraphicsView框架)
飞舞的蝴蝶(GraphicsView框架)
一、简介
GraphicsView框架结构主要包含三个主要的类QGraphicsScene(容器)、QGraphicsView(视图)、QGraphicsItem(图形项)。QGraphicsScene本身不可见必须通过与之相连的QGraphicsView视口类来显示及与外界进行互操作,主要提供项目的操作接口、传递事件和管理各个项目状态;QGraphicsView提供一个可视的窗口,用于显示场景中的项目,一个场景中可以有多个视口;QGraphicsItem是场景中各个项目的基础类。
二、关系图
(1)三者间的关系
(2)坐标系统
QGraphicsScene坐标系是以中心为原点(0,0),QGraphicsView继承自QWidget以窗口的左上角作为自己坐标系的原点,而QGraphicsItem则有自己的坐标系其paint()函数重画时以此坐标系为基准。
(3)坐标映射
三个坐标系之间的相互转换函数及图形项与图形项之间的转换函数。
三、详解
1、运行图
2、解析
(1)利用定时器实现QGraphicsItem不停上下飞舞的蝴蝶的动画效果
- #include <QGraphicsItem>
- #include <QObject>
- class Butterfly : public QObject, public QGraphicsItem
- {
- Q_OBJECT
- public:
- Butterfly();
- void timerEvent(QTimerEvent *);
- QRectF boundingRect() const;
- protected:
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
- private:
- bool up;
- QPixmap pix_up;
- QPixmap pix_down;
- qreal angle;
- };
- static const double PI = 3.14159265358979323846264338327950288419717;
- Butterfly::Butterfly()
- {
- setFlag(QGraphicsItem::ItemIsMovable);
- pix_up.load(":/images/butterfly1.PNG");
- pix_down.load(":/images/butterfly2.PNG");
- up = true;
- startTimer(100);
- }
- QRectF Butterfly::boundingRect() const
- {
- qreal adjust = 8;
- return QRectF(-pix_up.width()/2-adjust,-pix_up.height()/2-adjust,
- pix_up.width()+adjust*2,pix_up.height()+2*adjust);
- }
- void Butterfly::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
- {
- if(up)
- {
- painter->drawPixmap(boundingRect().topLeft(),pix_up);
- up = !up;
- }
- else
- {
- painter->drawPixmap(boundingRect().topLeft(),pix_down);
- up = !up;
- }
- // painter->setPen(Qt::NoPen);
- // painter->setBrush(Qt::darkGray);
- // painter->drawEllipse(-7,-7,40,40);
- // painter->setPen(QPen(Qt::black,0));
- // painter->setBrush(flash ? (Qt::red):(Qt::yellow));
- // painter->drawEllipse(-10,-10,40,40);
- }
- void Butterfly::timerEvent(QTimerEvent *)
- {
- // edge controll
- qreal edgex = scene()->sceneRect().right()+boundingRect().width()/2;
- qreal edgetop = scene()->sceneRect().top()+boundingRect().height()/2;
- qreal edgebottom = scene()->sceneRect().bottom()+boundingRect().height()/2;
- //qDebug() << scene()->itemsBoundingRect();
- if (pos().x() >= edgex)
- setPos(scene()->sceneRect().left(),pos().y());
- if (pos().y() <= edgetop)
- setPos(pos().x(),scene()->sceneRect().bottom());
- if (pos().y() >= edgebottom)
- setPos(pos().x(),scene()->sceneRect().top());
- angle += (qrand()%10)/20.0;
- qreal dx = fabs(sin(angle*PI)*10.0);
- qreal dy = (qrand()%20)-10.0;
- setPos(mapToParent(dx,dy));
- update();
- }
分析:在定时器的timeEvent()中对QGraphicsItem进行重画,重画paint()函数中飞舞的蝴蝶是由两幅图片组成,蝴蝶的移动边界做一个限定,dx和dy是相对于蝴蝶的坐标系而言的,调用setPos函数时使用mapToParent()函数映射成场景的坐标。setFlag(QGraphicsItem::ItemIsMovable);使蝴蝶可以通过鼠标移动。
(2)来回移动的星星
- class StarItem : public QGraphicsItem
- {
- public:
- StarItem();
- QRectF boundingRect() const;
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
- private:
- QPixmap pix;
- };
- StarItem::StarItem()
- {
- pix.load(":/images/star.png");
- }
- QRectF StarItem::boundingRect() const
- {
- return QRectF(-pix.width()/2,-pix.height()/2,pix.width(),pix.height());
- }
- void
- StarItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
- {
- painter->drawPixmap(boundingRect().topLeft(),pix);
- }
- {
- StarItem *star = new StarItem;
- QGraphicsItemAnimation *anim = new QGraphicsItemAnimation;
- anim->setItem(star);
- QTimeLine *timeLine = new QTimeLine(4000);
- timeLine->setCurveShape(QTimeLine::SineCurve);
- timeLine->setLoopCount(0);
- anim->setTimeLine(timeLine);
- int y = (qrand()%400) - 200;
- for (int i=0; i<400; i++)
- {
- anim->setPosAt(i/400.0, QPointF(i-200,y));
- }
- timeLine->start();
- scene->addItem(star);
- }
分析:利用QGraphicsItemAnimation类和QTimeLine实现项目的动画效果(也可使用定时器QTimer结合重绘函数来实现)。
(3)简单正方形
- {
- QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0,0,60,60));
- QPen pen;
- pen.setWidth(3);
- pen.setColor(QColor(qrand()%256,qrand()%256,qrand()%256));
- item->setPen(pen);
- item->setBrush(QColor(qrand()%256,qrand()%256,qrand()%256));
- item->setFlag(QGraphicsItem::ItemIsMovable);
- scene->addItem(item);
- //item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
- item->setPos(-200, -200);
- }
分析:利用继承QGraphicsItem的类QGraphicsRectItem添加一个正方形的图形项。
注意编译时会出现如下警告:
Warning::Class Butterfly imlements the interface QGraphicsItem but does not list it in Q_INTERFACES ;qobject_cast to QGraphicsItem will not work
原因:
QGraphicsItem的paint方法是在item被重绘时调用的,除了调用这个接口函数外,他还需要调用另外几个接口函数,你是不是在类中没有写呀?
需要添加的函数列表:
QRectF boundingRect() const;
QPainterPath shape() const;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent * event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent * event);
一、简介
GraphicsView支持事件传播体系结构,可以使图元在场景scene中得到提高了已被的精确交互能力。图形视图框架中的事件都是首先由视图进行接收,然后传递给场景,再由场景给相应的图形项。
对于键盘鼠标事件,scene会传递给获得焦点的图形项。如果场景没有获得焦点,那键盘事件会丢弃;如果调用场景setFocus()或者场景中的一个图形项获得了焦点,那么场景会自动获得焦点;如果场景丢失了焦点(如调用clearFocus())而其中一个图形项获得焦点那场景会保存这个图形项的焦点信息。
图形项默认无法接收悬停事件,可以使用QGraphicsItem的setAcceptHoverEvents()函数使图形项可以接收悬停事件。
二、运行图
(1)五个图形项的运行图如下图所示。
三、详解
1、QGraphicsScene
- #ifndef MYSCENE_H
- #define MYSCENE_H
- #include <QGraphicsScene>
- #include <QGraphicsSceneMouseEvent>
- #include <QPaintEvent>
- #include <QKeyEvent>
- class MyScene : public QGraphicsScene
- {
- Q_OBJECT
- public:
- explicit MyScene(QObject *parent = 0);
- protected:
- void keyPressEvent(QKeyEvent *event);
- void mousePressEvent(QGraphicsSceneMouseEvent *event);
- signals:
- public slots:
- };
- #endif // MYSCENE_H
- #include "myscene.h"
- MyScene::MyScene(QObject *parent) :
- QGraphicsScene(parent)
- {
- clearFocus();
- }
- void MyScene::keyPressEvent(QKeyEvent *event)
- {
- qDebug("*********MyScene::keyPressEvent***************");
- return QGraphicsScene::keyPressEvent(event);
- }
- void MyScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
- {
- qDebug("*********MyScene::mousePressEvent***************");
- QGraphicsScene::mousePressEvent(event);
- }
2、QGraphicsView
- #ifndef MYVIEW_H
- #define MYVIEW_H
- #include <QGraphicsView>
- class MyView : public QGraphicsView
- {
- Q_OBJECT
- public:
- explicit MyView(QWidget *parent = 0);
- protected:
- void keyPressEvent(QKeyEvent *event);
- void mousePressEvent(QMouseEvent *event);
- void paintEvent(QPaintEvent * event);
- void mouseMoveEvent(QMouseEvent *event);
- signals:
- public slots:
- };
- #endif // MYVIEW_H
- #include "myview.h"
- #include <QKeyEvent>
- MyView::MyView(QWidget *parent) :
- QGraphicsView(parent)
- {
- }
- void MyView::keyPressEvent(QKeyEvent *event)
- {
- qDebug("*********MyView::keyPressEvent***************");
- switch (event->key())
- {
- case Qt::Key_Left :
- scale(1.2, 1.2);
- break;
- case Qt::Key_Right :
- scale(1 / 1.2, 1 / 1.2);
- break;
- case Qt::Key_Up :
- rotate(30);
- break;
- }
- QGraphicsView::keyPressEvent(event);
- }
- void MyView::mousePressEvent(QMouseEvent *event)
- {
- qDebug("************MyView::mousePressEvent*****************");
- QGraphicsView::mousePressEvent(event);
- }
- void MyView::paintEvent(QPaintEvent *event)
- {
- qDebug("************MyView::paintEvent*****************");
- QGraphicsView::paintEvent(event);
- }
- void MyView::mouseMoveEvent(QMouseEvent *event)
- {
- //qDebug("************MyView::mouseMoveEvent*****************");
- QGraphicsView::mouseMoveEvent(event);
- }
3、QGraphicsItem
- #ifndef MYITEM_H
- #define MYITEM_H
- #include <QGraphicsItem>
- #include <QGraphicsSceneEvent>
- class MyItem : public QGraphicsItem
- {
- public:
- MyItem();
- QRectF boundingRect() const;
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
- QWidget *widget);
- void setColor(const QColor &color) { brushColor = color; }
- protected:
- void keyPressEvent(QKeyEvent *event);
- void mousePressEvent(QGraphicsSceneMouseEvent *event);
- void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
- void hoverLeaveEvent (QGraphicsSceneHoverEvent * event);
- void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
- void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
- private:
- QColor brushColor;
- };
- #endif // MYITEM_H
- #include "myitem.h"
- #include <QPainter>
- #include <QCursor>
- #include <QKeyEvent>
- #include <QGraphicsSceneHoverEvent>
- #include <QGraphicsSceneContextMenuEvent>
- #include <QMenu>
- MyItem::MyItem()
- {
- brushColor = Qt::red;
- setFlag(QGraphicsItem::ItemIsFocusable);
- setFlag(QGraphicsItem::ItemIsMovable);
- //setAcceptHoverEvents(true);
- }
- QRectF MyItem::boundingRect() const
- {
- qreal adjust = 0.5;
- return QRectF(-10 - adjust, -10 - adjust,
- 20 + adjust, 20 + adjust);
- }
- void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
- QWidget *widget)
- { qDebug("************MyItem::paint*****************");
- if(hasFocus()) {
- painter->setPen(QPen(QColor(255,255,255,200)));
- } else {
- painter->setPen(QPen(QColor(100,100,100,100)));
- }
- painter->setBrush(brushColor);
- painter->drawRect(-10, -10, 20, 20);
- }
- // 鼠标按下事件处理函数,设置被点击的图形项获得焦点,并改变光标外观
- void MyItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
- {
- qDebug("************MyItem::mousePressEvent*****************");
- setFocus();
- setCursor(Qt::ClosedHandCursor);
- }
- // 键盘按下事件处理函数,判断是否是向下方向键,如果是,则向下移动图形项
- void MyItem::keyPressEvent(QKeyEvent *event)
- {
- qDebug("************MyItem::keyPressEvent*****************");
- if(event->key() == Qt::Key_Down)
- moveBy(0, 10);
- }
- // 悬停事件处理函数,设置光标外观和提示
- void MyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
- {
- qDebug("************MyItem::hoverEnterEvent*****************");
- setCursor(Qt::OpenHandCursor);
- setToolTip("I am item");
- }
- void MyItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
- {
- qDebug("************MyItem::hoverLeaveEvent*****************");
- setCursor(Qt::ArrowCursor);
- }
- // 右键菜单事件处理函数,为图形项添加一个右键菜单
- void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
- {
- QMenu menu;
- QAction *moveAction = menu.addAction("move back");
- QAction *actAction = menu.addAction("test");
- QAction *selectedAction = menu.exec(event->screenPos());
- if(selectedAction == moveAction) {
- setPos(0, 0);
- }
- }
- void MyItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
- {
- qDebug("************MyItem::mouseMoveEvent*****************");
- QGraphicsItem::mouseMoveEvent(event);
- }
4、main及运行
- #include <QApplication>
- #include "myitem.h"
- #include "myview.h"
- #include "myscene.h"
- #include <QTime>
- int main(int argc,char* argv[ ])
- {
- QApplication app(argc,argv);
- qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
- MyScene scene;
- scene.setSceneRect(-200, -150, 400, 300);
- for(int i = 0; i < 5; ++i) {
- MyItem *item = new MyItem;
- item->setColor(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
- item->setPos(i * 50 - 90, -50);
- scene.addItem(item);
- }
- MyView view;
- view.setScene(&scene);
- view.setBackgroundBrush(QPixmap(":/background.png"));
- view.show();
- return app.exec();
- }
分析:keyPressEvent键盘按下事件由View—Scene—Item
分析:mousePressEven鼠标按下事件由View—Scene—Item
分析:事件项Item没有获得焦点时,mousePressEven鼠标按下事件只由View传递到Scene。
分析:事件项Item的悬停事件,在构造函数中设置了setAcceptHoverEvents(true)。
飞舞的蝴蝶(GraphicsView框架)的更多相关文章
- Qt的Graphics-View框架和OpenGL结合详解
Qt的Graphics-View框架和OpenGL结合详解 演示程序下载地址:这里 程序源代码下载地址:这里 这是一篇纯技术文,介绍了这一个月来我抽时间研究的成果. Qt中有一个非常炫的例子:Boxe ...
- Qt浅谈之十八:GraphicsView框架事件处理(有源码下载)
一.简介 GraphicsView支持事件传播体系结构,可以使图元在场景scene中得到提高了已被的精确交互能力.图形视图框架中的事件都是首先由视图进行接收,然后传递给场景,再由场景给相应的图形项. ...
- pyqt5.0 GraphicsView框架
场景(The Scene) QGraphicsScene提供图形视图场景.该场景具有以下职责: 提供用于管理大量图元的快速界面(锅) 将事件传播到每个图元(把螃蟹烧熟了) 管理图元状态,例如选择和焦点 ...
- Android中的动画具体解释系列【2】——飞舞的蝴蝶
这一篇来使用逐帧动画和补间动画来实现一个小样例,首先我们来看看Android中的补间动画. Android中使用Animation代表抽象的动画类,该类包含以下几个子类: AlphaAnimation ...
- Android中的动画详解系列【2】——飞舞的蝴蝶
这一篇来使用逐帧动画和补间动画来实现一个小例子,首先我们来看看Android中的补间动画. Android中使用Animation代表抽象的动画类,该类包括下面几个子类: AlphaAnimation ...
- Qt 动画框架
最近一个项目中的需要做动画效果,很自然就想起来用qt animation framework .这个框架真的很强大.支持多个动画组合,线性动画,并行动画等.在此总结一下使用该框架一些需要注意的地方: ...
- 【转】QT Graphics-View官方介绍(中文翻译)
一.GraphicsView框架简介 QT4.2开始引入了Graphics View框架用来取代QT3中的Canvas模块,并作出了改进,Graphics View框架实现了模型-视图结构的图形管理, ...
- QT Graphics-View 3D编程例子- 3D Model Viewer
学习在Graphics-View框架中使用opengl进行3D编程,在网上找了一个不错的例子“3D Model Viewer”,很值得学习. 可以在http://www.oyonale.com/acc ...
- QT学习笔记4:QT中GraphicsView编程
一.QGraphicsScene 1.QGraphicsScene QGraphicsScene继承自QObject,是一个管理图元的容器,与QGraphicsView合用可以在2D屏幕上显示如线.三 ...
随机推荐
- 向日期添加指定的时间间隔(mysql)
DATE_ADD( 原始日期, INTERVAL 要加的年数 YEAR) DATE_ADD( 原始日期, INTERVAL 要加的月份 MONTH) DATE_ADD( 原始日期, INTERVAL ...
- Oracle dba权限下修改用户密码 授予用户权限 解锁用户
1.修改用户密码 alter user scott identified by 123 2.授予用户权限 grant connect,resource to scott 3.解锁用户 alter us ...
- artDialog基本使用
artDialog是一个基于javascript编写的对话框组件,它拥有精致的界面与友好的接口l 自适应内容artDialog的特殊UI框架能够适应内容变化,甚至连外部程序动态插入的内容它仍然能自适 ...
- Python数据结构 将列表作为栈和队列使用
列表作为栈使用 Python列表方法使得列表作为堆栈非常容易,最后一个插入,最先取出(“后进先出”).要添加一个元素到堆栈的顶端,使用 append() .要从堆栈顶部取出一个元素,使用 pop() ...
- 【java请求】- jmeter_jdbc脚本实战
一,导入 使用Jmeter运行Java脚本,需要用到Jmeter的提供的框架jar包(分别在jmeter目录下的lib和ext目录下)1.ApacheJMeter_core.jar2.ApacheJM ...
- javascript 强制转换规则 boolean 布尔值类型
摘自 <你不知道的Javascript(中卷)> p55 一句话简述, 假值表以外的值均可以认为是真值,部分浏览器可能自定义了假值表以外的假值,并不符合W3C规范,需要特殊对待. 首先也是 ...
- 多主机Docker容器的VLAN划分
原文发表于cu:2016-06-06 参考文档: Docker网络的4种模式,pipework/ovs的简单使用等:http://www.infoq.com/cn/articles/docker-ne ...
- js页面跳转,url带url参数解决方案
今天,在做一个项目的时候,向后端发送了一个Ajax请求,后端返回了一个字符串,告诉我未登录.那么我需要跳转到登录页面,同时告诉登录页面,登录成功后,需要跳回的url.也就是标题所说,url中的一个参数 ...
- Python模块random使用详情
python常用模块目录 1.random.random()#用于生成一个0到1的随机浮点数:0<= n < 1.0 import random mcw = random.random() ...
- 微信小程序---scroll-view在苹果手机上触底或触顶页面闪动问题
在项目开发中遇到一个关于scroll-view的的问题,具体如下: 项目要求是横向滚动,由于直接在scroll-view组件设置display:flex不生效,因此考虑直接在scroll-view下增 ...