飞舞的蝴蝶(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屏幕上显示如线.三 ...
随机推荐
- 【转】RobotFrameWork+APPIUM实现对安卓APK的自动化测试----第二篇【原理】
接着上一篇,我们开始聊聊APPIUM的框架和运行模式.废话不多说直接上图. 1.首先自动化脚本通过RobotFrameWork将命令传递给Appium的客户端: 2.然后[Appium的客户端]将接受 ...
- 第一篇 数据库MySql
数据库的简介 数据库:存储数据的仓库 数据库管理系统软件 常见的数据库管理软件:甲骨文的oracle,IBM的db2,sql server, Access,Mysql(开源,免费,跨平台). 关系型数 ...
- 一、初识 Django
一.引子 Django最初设计用于具有快速开发需求的新闻类站点,目的是要实现简单快捷的网站开发! 从好的方面来看,Web 开发激动人心且富于创造性:从另一面来看,它却是份繁琐而令人生厌的工作.通过减少 ...
- Spring学习(1):侵入式与非侵入式,轻量级与重量级
一. 引言 在阅读spring相关资料,都会提到Spring是非侵入式编程模型,轻量级框架,那么就有必要了解下这些概念. 二. 侵入式与非侵入式 非侵入式:使用一个新的技术不会或者基本不改变原有代码结 ...
- 2019CSUST集训队选拔赛题解(一)
来自ppq的毒瘤线段树 Sneakers Description 有一天喜欢买鞋的ppq和小伙伴来到了某一家球鞋店,球鞋店有n种球鞋,价格分别为ai,ppq在鞋店兜兜转转,发现鞋店老板会偶尔将某段 ...
- GitLab 搭建与使用
操作系统:Centos 7 环境:VM虚拟机 0x00:这里说下VM 虚拟机的配置 然后选择NAT模式 接下来配置网络 cd /etc/sysconfig/network-scripts/ 编辑:vi ...
- Web安全入门书籍推荐
<Web应用安全权威指南> 链接:https://pan.baidu.com/s/1wZgv3c9jhWm1bAUHZw3gEg 提取码:teqj <黑客攻防技术宝典__Web实战篇 ...
- 如何把node更新到最新的稳定版本
先装n,再用n把node升级到最新稳定版 $ npm install -g n $ n stable
- python3【基础】-集合
集合( set):把不同的元素组成一起形成集合,是python基本的数据类型. 集合元素(set elements):组成集合的成员(不可重复) class set(object) | set() - ...
- 冲刺ing-2
第二次Scrum冲刺 队员完成的任务 队员 完成任务 吴伟华 分配任务 蔺皓雯 编写博客,查阅资料 蔡晨旸 查阅资料 曾茜 暂无 鲁婧楠 暂无 杨池宇 暂无 成员遇到的问题 队员 问题 吴伟华 暂无 ...