Qt图形视图、动画、状态机框架
Qt学习笔记--图形视图框架
Qt学习笔记--图形视图框架(一)2010-07-11 07:40优点:处理多个图元,单击,拖动,选择图元架构:一个场景,多个图元位于其中,通过视图显示主要应用: 绘图软件,显示地图软件当使用没有变换的视图观察场景时,场景中的一个单元对应屏幕上的一个像素图元坐标通常以图元中心为原点,X轴正方向为向右,Y轴正方向为向下场景坐标的原点在场景中心,X轴正方向为向右,Y轴正方向为向下视图坐标以左上角为原点,X轴正方向为向右,Y轴正方向为向下所有的鼠标事件最开始都是使用视图坐标场景:图元的容器1.提供管理很多图元的接口2.传播事件到图元中3.管理图元状态,例如选择和焦点处理4.提供非转换的绘制功能,主要用于打印QGraphicsScene scene;QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100)); // 添加图元QGraphicsItem *item = scene.itemAt(50, 50); // 查询图元// item == rect;通过QGraphicsScene::setSelectionArea()可以选择场景的任一个图元,QGraphicsScene::setSelectedItems()返回被选择的图元设置焦点图元QGraphicsScene::setFocusItem(), setFocus(), QGraphicsScene::focusItem(), 返回焦点图元视图:一个可视的子部件,可视化场景的内容多个视图可以显示同一个场景坐标转换:QGraphicsView::mapToScene(), QGraphicsView::mapFromScene()图元:支持鼠标事件,滚轮事件,上下文菜单事件支持键盘输入焦点,按键事件支持拖放支持分组冲突探测提供坐标转换,图元与场景,图元与图元之间利用QGraphicsItem::shape()和QGraphicsItem::collidesWith()实现冲突探测,这2个函数都是虚函数相关类:QGraphicsScene, QGraphicsItem, QGraphicsViewQGraphicsItem子类:QGraphicsEllipseItem provides an ellipse itemQGraphicsLineItem provides a line itemQGraphicsPathItem provides an arbitrary path item QGraphicsPixmapItem provides a pixmap itemQGraphicsPolygonItem provides a polygon itemQGraphicsRectItem provides a rectangular item QGraphicsSimpleTextItem provides a simple text label itemQGraphicsTextItem provides an advanced text browser item QGraphicsSvgItem provides a SVG file itemQGraphicsScene:拥有多个图元,包含三层:背景层,图元层,前景层背景层和前景层可以使用QBrush绘制,也可以使用drawBackground(),drawForeground()实现如果使用图片作为背景,可以用texture QBrush(pixmap)实现前景层brush可以使用半透明的白色实现褪色效果,或者使用交叉模式实现网格重叠场景可以告诉我们,哪些图元发生冲突,哪些图元被选择,哪些图元位于一个特定的点或者区域每个图元可以是:1.顶级图元,场景是它的父亲;2.孩子,它的父亲是另一个图元,任何作用于父图元的转换都将自动应用于它的孩子2种分组方式:1.一个图元成为另一个图元的孩子;2.使用QGraphicsItemGroup。
图形视图、动画和状态机框架
准
QGraphicsPolygonItem:提供一个多边形item
图
QGraphicsLineItem:提供一条线的item
形
QGraphicsPathItem:提供一个任意的路径item QGraphicsSimpleTextItem:提供一个文字图标item
项
QGraphicsTextItem:提供一个文本浏览item
行管理。(真实世界)
视图(QGraphicsView):用来使场景中的内容可视化。
每个视图提供一个视口。对于同一个场景,可以使用不同的视图
对象实现不同的可视化效果。(不同的人、动物、甚至事物看到 的世界)
QGraphicsRectItem:提供一个矩形item
标
QGraphicsEllipseItem:提供一个椭圆item
QGraphicsPixmapItem:提供一个图形item
相关函数
scene.addItem(item):向场景中添加已有的图形项 scene.addRect():新建标准图形项(矩形),并添加到场景中。 scene.itemAt(QPoint):返回指定位置处最顶层可视的图形项。 scene.items():返回满足特定条件的所有图形项。
标准图形效果类
QObject QGraphicsEffect
QGraphicsBlurEffect:模糊效果 QGraphicsColorizeEffect:着色效果 QGraphicsDropShadowEffect:阴影效果 QGraphicsOpacityEffect:半透明效果
原图 模糊 半透明
相关函数
item.setPos():设置图形项在场景中的位置。 item.pos():返回图形项在场景(父对象)中的位置。 item.setZValue():设置图形项的Z值,Z值越大越靠上。
Qt图形视图框架三——坐标系统
Qt图形视图框架三——坐标系统⼀基础知识 图形视图框架是基于笛卡尔坐标系统的,⼀个图形项在场景中的位置和⼏何形状由x坐标和y坐标来表⽰。
当使⽤⼀个没有变换的视图来观察场景时,场景中的⼀个单元代表屏幕上的⼀个像素。
图形视图框架的三个坐标系分别是视图坐标系、场景坐标系和图元坐标系。
三个坐标系分别由视图、场景和图元使⽤。
为了⽅便应⽤,图形视图框架中提供了⼀些便捷函数来完成3个坐标系统之间的映射。
当进⾏绘图时,场景坐标对应QPainter的逻辑坐标,视图坐标对应设备坐标。
⽐如在给场景中添加图元时,图元的位置就是相对于场景坐标系⽽⾔的:1.1 场景坐标系 场景坐标系是所有图元对象的绝对坐标. 有四个象限,场景坐标是所有图形项的基础坐标系统。
场景坐标系统描述了每⼀个顶层图形項的位置,也形成了所有从视图传到场景上的事件的基础。
场景坐标的原点在场景的中⼼,x轴正⽅向向右,y轴正⽅向向下。
每⼀个在场景中的图形项除了拥有⼀个图形項的本地坐标和边界矩形外,还都拥有⼀个场景坐标(QGraphicsItem: :scenePos())和⼀个场景中的边界矩形(QGraphicsItem::sceneBoundingRect())。
场景坐标⽤来描述图形项在场景坐标系统中的位置,⽽图形项的场景边界矩形⽤于QGraphicsScene判断场景中的哪些区域进⾏了更改。
常⽤添加图元函数:QGraphicsScene::setBackgroundBrush //填充背景⾊QGraphicsScene::setForegroundBrush //填充前景⾊QGraphicsScene::addSimpleText //添加简单⽂本QGraphicsScene::addLine //添加直线QGraphicsScene::addRect //添加矩形QGraphicsScene::addEllipse //添加椭圆QGraphicsScene::addWidget //添加窗⼝QGraphicsScene::addPixmap //添加图⽚操作图元函数:QGraphicsScene::itemAt //查找场景某个中最表层的itemQGraphicsScene::setSelectionArea //设置选定区域QGraphicsScene::setSceneRect //设置场景的区域⼤⼩QGraphicsScene::itemsBoundingRect //根据所有的item计算区域⼤⼩QGraphicsScene:: selectedItems //获取被选中的item,item必须为可选QGraphicsItem::ItemIsSelectableQGraphicsScene类的坐标系以中⼼为原点(0,0),如下图所⽰。
详解Qt中的状态机机制
详解Qt中的状态机机制(一)*****************************************************************************欢迎访问我的博客:/u010977122/article/details/52959098****************************************************************************状态机,简写为FSM(Finite State Machine),状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。
在GUI开发的时候,界面复杂的逻辑往往令人抓狂,逻辑都不清晰,代码写起来更加费劲。
用户界面设计中采用状态驱动,就可以使得GUI 的逻辑更加清晰。
根据当前状态的不同,显示不同的界面。
程序界面可以被看作显示对应不同场景,或者是通过改变外观响应用户的交互。
通常情况下,界面中很多个组件的改变是并发进行的,这样的界面可以看作从一个状态改变到另外一个状态。
今天我们来看看qt中的状态机框架,qt把它作为QtCore中的一个模块,也足见其重要性:Qt状态机框架提供了一些类来创建执行状态图,状态图为一个系统如何对外界激励进行反应提供了一个图形化模型,该模型是通过定义一些系统可能进入的状态以及系统怎样从一个状态切换到另一个状态来实现的。
事件驱动的系统的一个关键特性就是它的行为不总是仅仅依赖于前一个或者当前的事件,而且也依赖于将要执行的事件。
通过使用状态图,这些信息会非常容易进行表达。
状态机框架提供了一套API以及一种执行模型,可以有效地将状态图的元素和语义嵌入到Qt应用程序中。
该框架与Qt的元对象系统结合紧密:例如,不同状态之间的转化可由信号触发,信号驱动,且状态可配置用于QObject的属性和方法。
在进入今天的主题之前,我们先来了解三个概念:状态(State):是静态的东西,对一系列对象属性的一组静态描述和配置。
QT图形视图框架
QT图形视图框架使⽤QPushButton、QLabel、QCheckBox等构成GUI的控件或⾃定义图形时,开发应⽤程序会变得很简单。
但是如果想在GUI中使⽤数⼗个或者数百个图形对象,向⽤户完美展⽰控制场景,则会受到很多的限制。
图形视图框架⽤来管理2D图形项,⽀持绘制、缩放、事件响应等等。
1、快速提供并管理⼤量对象2、将事件传递到每⼀个对象3、管理焦点处理或对象选择等状态图形视图框架是按照MVC设计模式绘图, MVC设计模式包括三个元素:数据的模型(Model),⽤户界⾯的视图(View) ,⽤户再界⾯上的操作控制Controller。
QGraphicsViewQGraphicsView 是为了在场景上显⽰图元⽽提供的类。
QGraphicsView包括可视控件区域和⽤于显⽰⼤场景滚动区域,可以接受⽤户输⼊事件。
QGraphicsView间接继承⾄QWidget。
QGraphicsSceneQGraphicsScene类可以保存图元,也可以处理⽤户输⼊事件。
是图形对象QGraphicsItem的容器,为管理⼤量的items提供⼀个快速的接⼝。
QGraphicsScene只继承⾃QObject,所以本⾝是不可见的,必须通过与之相连的视图类QGraphicsView来显⽰.QGraphicsItemQGraphicsItem是为了在图形视图上实现图形对象⽽提供的类。
⽀持⿏标、键盘、焦点事件,⽀持拖放,在它的基础上可以继承出各种图元类。
⽀持碰撞检测collision detection.1 QGraphicsScene的常⽤函数常⽤添加图元函数QGraphicsScene::setBackgroundBrush //填充背景⾊QGraphicsScene::setForegroundBrush //填充前景⾊QGraphicsScene::addSimpleText //添加简单⽂本QGraphicsScene::addLine //添加直线QGraphicsScene::addRect //添加矩形QGraphicsScene::addEllipse //添加椭圆QGraphicsScene::addWidget //添加窗⼝QGraphicsScene::addPixmap //添加图⽚例如:#include <QApplication>#include <QGraphicsView>#include <QGraphicsRectItem>#include <QLabel>int main(int argc, char** argv){QApplication app(argc, argv);QGraphicsView view;QGraphicsScene scene;view.setScene(&scene);view.show();view.resize(400, 400);/*设置场景的背景⾊前景⾊*/scene.setBackgroundBrush(QBrush(Qt::red));scene.setForegroundBrush(QBrush(QColor(0, 255, 0, 50)));/*添加线*/scene.addLine(0, 0, 100, 100, QPen(Qt::black));/*添加矩形*/scene.addRect(0, 100, 100, 100, QPen(Qt::yellow), QBrush(Qt::blue));/*添加椭圆*/scene.addEllipse(100, 0, 100, 100, QPen(Qt::red), QBrush(Qt::green));/*添加简单⽂本,并且设置⽂本字体,并且描边*/scene.addSimpleText("hello", QFont("system", 40))->setPen(QPen(QBrush(Qt::yellow), 3));/*添加图⽚,并且移动位置*/scene.addPixmap(QPixmap("E:\\qt_workspace\\pic\\wallet.png"))->setPos(200, 200);/*添加⼀个窗⼝*/QLabel label("widget");scene.addWidget(&label);return app.exec();}操作图元函数QGraphicsScene::itemAt //查找场景某个中最表层的itemQGraphicsScene::setSelectionArea //设置选定区域QGraphicsScene::setSceneRect //设置场景的区域⼤⼩QGraphicsScene::itemsBoundingRect //根据所有的item计算区域⼤⼩QGraphicsScene:: selectedItems //获取被选中的item,item必须为可选QGraphicsItem::ItemIsSelectable 2 QGraphicsItem的常⽤函数QGraphicsItem::rect //不带边框的图形区域QGraphicsItem::boundingRect //带边框的图形区域QGraphicsItem::collidesWithItem //碰撞检测QGraphicsItem::setScale //缩放QGraphicsItem::setRotation //旋转QGraphicsItem::setZValue //设置z坐标,图元的叠加先后顺序可以⽤它来设置QGraphicsItem::setPos //设置位置坐标设置item的属性void QGraphicsItem::setFlags(GraphicsItemFlags flags);/**参数GraphicsItemFlags flags 为枚举类型,可以以下值* QGraphicsItem::ItemIsMovable 是否可以移动* QGraphicsItem::ItemIsSelectable 是否可以被选中* QGraphicsItem::ItemIsFocusable 是否可以设置为焦点item*/3 图形视图的坐标系3.1 QGraphscItem图元坐标系图元对象都有⾃⾝的坐标系,坐标系以(0,0)为坐标原点,⾃左向右递增是x轴,⾃上⽽下递增是y轴,⽽且所有图元对象的移动转换作⽤点都是(0, 0),坐标值可以是浮点型数值。
【图书】【C 】【QT】QT图形用户界面应用程序框架解析
X
画布模块 为可视化效果,图表和其它而优化的二维图形领 域。
表格模块 灵活的可编辑的表格/电子表格
X
X
XML模块 通过SAX接口和DOM Level 1很好且已经成形的 XML解析器。
SQL模块 SQL数据库访问类。
X
X
使用Qt快速地构建流行的GUI
GUN协议
为保证 GNU 软件可以自由地“使用、复制、修改和 发布”,所有 GNU 软件都包含一份在禁止其他人添 加任何限制的情况下,授权所有权利给任何人的协议 条款,GNU通用公共许可证(GNU General Public License,GPL)。这个就是被称为“反版权”的概 念。GNU 也针对不同场合,提供GNU宽通用公共许 可证 (GNU Lesser General Public License, LGPL) 与GNU自由文档许可证 (GNU Free Documentation License, GFDL) 这两种协议条款。
关于Qt
停靠窗口
停靠窗口是指用户可以在工具栏区域内或区域 间随意移动的窗口。用户可以对停靠窗口解锁, 使该窗口浮在应用程序顶部,也可以使窗口最 小化。
Qt Designer 设计者工具
功能强大的GUI 布局与窗体构造器,能够在所有支持平台上,以本地化 的视图外观与认知,快速开发高性能的用户界面。
关于Qt
Qt是一个用于桌面系统和嵌入式开发的跨平台 应用程序框架 ,由挪威TrollTech公司出品 用于本地化跨平台应用开发的领先性框架 对不同平台(Unix, Windows, and Mac)对 API进行了封装,如文件处理、网络(操作, 协议),进程处理、线程、数据库访问等
Qt图形视图体系结构示例解析(视图、拖拽、动画)
Qt图形视图体系结构⽰例解析(视图、拖拽、动画) 本博的⽰例来⾃与QT Example:C:\Qt\Qt5.9.3\Examples\Qt-5.9.3\widgets\graphicsview\dragdroprobot 将通过分析⽰例完成主要功能: (1)颜⾊图元绘制 (2)机器⼈图元绘制 (3)颜⾊图元的⿏标事件 (4)机器⼈图元的DragDrop事件 (5)图元动画效果⼀、颜⾊图元类实现 QGraphicsItem作为所有图元类的基类,⾃定义图元类需继承QGraohicsItem类,实现其基类的纯虚函数virtual QRectF boundingRect() const = 0;virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR) = 0; boundingRect()设置图元的边界矩形范围,QGraphicsView使⽤此来确定图元是否需要重绘 paint()实现图元的绘制操作,⼀种⽅法是直接在paint中对图元进⾏绘制。
另⼀种⽅法可以通过shape返回QPainterPath,然后在paint中依据QPainterPath进⾏绘制 该⽰例实现了随机的10中颜⾊图元,boundRect()为QRectF(-15,-15,30,30),图元的中⼼坐标为(0,0)(1)⾃定义随机颜⾊m_pColor(qrand() % 256, qrand() % 256, qrand() % 256)(2)图元边界矩形设置QRectF ColorItem::boundingRect() const{return QRectF(-15,-15,30,30);}(3)图元绘制void ColorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){painter->setBrush(m_pColor);painter->drawEllipse(boundingRect());}(4)光标设置 当⿏标进⼊图元或是拖动图元时设置光标形状,光标形状查看枚举类型:CursorShapesetCursor(Qt::OpenHandCursor);setAcceptedMouseButtons(Qt::LeftButton);(5)设置ToolTip 当⿏标进⼊图元时显⽰提⽰内容:setToolTip(QString("QColor(%1,%2,%3)\n%4").arg(m_pColor.red()).arg(m_pColor.green()).arg(m_pColor.blue()).arg("Click and drag this color onto the robot!"));⼆、机器⼈头像图元类实现 颜⾊图元的实现中已经了解了基本实现⽅法,机器⼈图元的实现也不例外,由于机器⼈包括很多图元部分(头、⾝体等),我们可以采⽤⾯对对象继承的⽅式来实现。
QT图形视图框架(The Graphics View Framework)
管理 widgets 在图形视图中的布局 在 QGraphicsScene 中所有图形对象的基 类 为 QGraphicsItem 提供简单的 动画支持 将多个图形对象组合成一个对象 图形视图中所有布局类的基类 允许布局类管理的自定义对象 直线对象,可以直接添加到 QGraphicsScene 管理 widgets 在图形视图中的的水平或者 垂直方向上的布局 所有需要处理信号 /槽 /属性的图形对象。 路径对象,可以直接添加到 QGraphicsScene 位图对象,可以直接添加到 QGraphicsScene 多边形对象,可以直接添加到 QGraphicsScene widget 代理,用于将一个 QWidget 对象嵌 入 一个 QGraphicsScene 中 矩形对象,可以直接添加到 QGraphicsScene 管理大量二维图形对象的管理器
• • • • •
鼠标按下、移动、释放和双击事件,同时还支持鼠标悬浮事件、滚轮事件和上下文菜单事件。 键盘输入焦点和键盘事件。 拖放。 组合:通过父对象 -子对象进行组合,或者通过 QGraphicsItemGroup 组合。 碰撞检测。
与 QGraphicsView 类似,处于局部坐标系下的图形对象,也提供了图形对象和场景之间的映射函数。 和 QGraphicsView 一样,图形对象同时还可以通过矩阵来变换其自身的坐标系统,这一点对于单个 图形对象的旋转和缩放非常有用。 图形视图架构 个图形对象可以包含其他对象(子对象)。父对象的变换矩阵同样也会应用到子对象上。但是,不管一 个对象累积了多少变换, QGraphicsItem::collidesWith()仍然会在局部坐标系下进行计算。
图形视图框架
The Graphics View Framework
Qt框架及模块认识
Qt框架及模块认识⼩⽩⾃⼯作就接触Qt,⼀直都在使⽤Qt5.3.1版本,所以没有经历过⼤⽜们把项⽬从Qt4程序到Qt5的烦恼,没准以后会碰到。
对Qt所有的丰富的API表⽰惊叹,对于Qt的框架及模块认识也是极为模糊的,⽂中有不对之处希望⼤⽜们打脸(虽然脸都已经被打肿了。
)1、Qt的跨平台性(Linux、Unix、、Mac OS、Android、IOS)简⽽⾔之:Qt的功能是建⽴在它所⽀持的平台底层API之上的。
Qt/Windows对应的是GDI(Graphics Device Interface),很容易就知道它是Qt封装的与GDI交流的API。
⽽GDI是Windows下图形绘制及显⽰的主要API。
Qt/X11同样是对X Windows的编程接⼝。
Linux本⾝是没有操作界⾯的,⽬前主流带有操作界⾯的Linux系统都是基于X WIndows的,已经列⼊了Linux发⾏标准软件了。
X Windows是C/S框架的(就是所有的⿏标事件传递到X Windows的服务端处理之后对应在屏幕上显⽰内容),Qt/X11使⽤Xlib直接与X服务器通信的。
(GDI是集成到Windows内核的,⽽X Windows只是Linux系统的应⽤软件⽽已)Qt/Macintosh就不⽤说了。
Carbon是Mac OS X下应⽤程序开发环境,包含了应⽤程序的图形部分。
⽬前主流的Cocoa好像使⽤更好。
上图主要说明的是UI部分,Qt跨平台都是调⽤本地的图形风格。
三种操作系统都⽀持主流的⽂件系统(⽂件系统并不是操作系统固有的,⽂件系统描述的硬盘⾥⾯⽂件存储和查找的⽅式),通信都是采⽤socket框架(socket是⽹络时代的产物,那时候的操作系统已经很成熟了)。
⾄此可以⼤致了解了Qt跨平台的基本原理了。
Qt框架在Qt帮助⾥⾯搜索All modules可以清楚的看到Qt的模块分布。
Qt Essentials(Qt的基本模块)这⾥指的是开发者会经常使⽤到的稳定模块。
QT开始学习图形视图框架(TheQGraphicsViewFramework)
QT开始学习图形视图框架(TheQGraphicsViewFramework)图形视图提供了一个外表(surface)来实现大量的客户所做的2D图形项的管理和相互的结合;一个视图窗口部件来使这些项可视化,并支持缩放和旋转。
该框架包括一个事件传播体系,可以使得场景中的项的交叉可以达到双精度的精确控制。
其中的项可以处理事件、鼠标按压、移动、释放和双击事件,它们也可以追踪鼠标的移动。
图形视图使用一个BSP(二进制空间分区Binary Space Partitioning)树来提供快速的项发现,正因为如此,它可以使巨大的场景实时地可视化,即便它有上百万个项(item)。
图形视图是在Qt4.2中引入的,取代了以前的QCanvas,如果需要从QCanvas移植,参见“Porting to Graphics View”主题:l 图形视图的体系架构场景(Scene)视图(View)项(Item)l 图形视图的坐标系统项坐标场景坐标视图坐标坐标映射l 主要的特性缩放和旋转打印拖放光标和提示动画OpenGL展示项的成组窗口部件和布局嵌入式窗口部件支持图形视图体系架构图形视图提供了基于项的模型—视图编程方式,很象交互视图(InterView)的方便的类如QTableWidget,QTreeWidget,QListWidget。
多个视图可以用来观察一个场景,场景包含了变化的几何形状的项。
场景(Scene)QGraphicsScene提供了图形视图的场景,场景承担下列的责任:提供一个快速的接口用来管理大量的项。
向每个项传递事件。
管理项的状态,如选中、焦点处理。
提供无变形的展示功能,主要为了打印。
场景作为QGraphicsItem对象的容器,项可以调用QGraphicsScene::addItem()加入场景。
QGraphicsScene::items()和它的重载可以返回所有的项,包括点、长方形、多边形、通用矢量路径。
QGraphicsScene::itemAt()返回在特定点上最上边的项。
QT动画框架
动画框架(The Animation Framework)QT的动画框架也是引入至QT4.6,很有可能是配合图形系统框架为了下一代UI 做的铺垫动画框架的类:QAbstractAnimation The base of all animations QAnimationGroup Abstract base class for groups of animations QEasingCurve Easing curves for controlling animation QParallelAnimationGroup Parallel group of animations QPauseAnimation Pause for QSequentialAnimationGroup QPropertyAnimation Animates Qt properties QSequentialAnimationGroup Sequential group of animationsQTimeLine Timeline for controlling animations QVariantAnimation Abstract base class for animations类别狭义的来说,Animation Framework指的是以QAbstractAnimation为基类的几个相关的Animation类,主要用途是用于动画QWidget/QObject的属性(property)稍微放宽一点来说,还包括QTimeLine,顾名思义,它并不直接绑定并修改某个对象属性,而是根据设定的时间轴,发送信号,用于绑定特定slot,执行相关操作,所以应该不止动画,也不限于属性,你可以用它来做任何你想做的和时间轴相关的事。
其次,还有专用于QGraphicsItem的QGraphicsItemAnimation类,它主要和QTimeLine配合,控制QGraphicsItem的坐标变换矩阵再广义一点,QT状态机在状态转换时可以绑定设置控件属性,你也可以认为这是一种动画效果,当然,如果不和一个Animation类配合的话,属性值的改变是瞬间完成的,没有中间动画过程。
第7章Qt5图形视图框架课件
7.2.1 飞舞的蝴蝶
在重画函数paint()中,首先判断当前已显示的图片是pix_up还是pix_down。 实现蝴蝶翅膀上下飞舞效果时,若当前显示的是pix_up图片,则重绘pix_down图 片,反之亦然。具体实现代码内容如下:
void Butterfly::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
QApplication a(argc,argv); QGraphicsScene *scene = new QGraphicsScene; scene->setSceneRect(QRectF(-200,-200,400,400)); Butterfly *butterfly = new Butterfly; butterfly->setPos(-100,0); scene->addItem(butterfly); QGraphicsView *view = new QGraphicsView; view->setScene(scene); view->resize(400,400); view->show(); return a.exec(); }
7.1.3 GraphicsView的坐标系统
Graphics View框架提供了多种坐标变换函数,见表7.1。
Qt图形视图框架一——QGraphicsItem
Qt图形视图框架⼀——QGraphicsItem⼀、概念介绍 之前最项⽬,⼀直在⽤2D绘图的QGraphics/view,由于今年肺炎疫情的影响⽆法出门,所以有时间把这块做⼀个总结。
在我们平时绘图中,如果我们在⼀块画布上绘制多个不规则图形并且还要监控每⼀个图形的⾏为(⽐如移动、叠加、碰撞、拖动、缩放、旋转等操作)时,我们就要⽤到Qt⾥的图形视图框架,QGraphicScene(场景)可以管理多个图形项QGraphicsItem(⽐如:QGraphicsRectItem(矩形的图形项,也就是图元)),QGraphicsView(视图)关联场景可以让场景中的所有图形项可视化,其次还提供了缩放和旋转,可以帮助⽂档中搜索Graphics View 关键字查阅。
⼆、简单应⽤⽰例 分别新建了⼀个场景,⼀个矩形图形项和⼀个视图,并将图形项添加到场景中,将视图与场景关联,最后显⽰视图就⾏了,场景是管理图形项的,所有的图形项必须添加到⼀个场景中,但是场景本⾝⽆法可视化,要想看到场景上的内容,必须使⽤视图,代码如下:#include <QtWidgets>#include <QApplication>int main(int argc,char* argv[ ]){QApplication app(argc,argv);// 场景QGraphicsScene *scene = new QGraphicsScene;// 矩形项QGraphicsRectItem *item =new QGraphicsRectItem(150,150,50,50);// 项添加到场景scene->addItem(item);// 视图QGraphicsView *view = new QGraphicsView;// 视图关联场景view->setScene(scene);// 显⽰视图view->show();return app.exec();}运⾏如下:三、图像项QGraphicsItem QGraphicsItem类是所有图形项的基类。
Qt图形视图框架
QGraphicsScene类的坐标系以中心为原点(0,0),如图所示。
第3页/共17页
7.1.3 GraphicsView的坐标系统
2.视图坐标
QGraphicsView类继承自QWidget类,因此它与其他的QWidget类一样,以窗口 的左上角作为自己坐标系的原点,如图所示。
第4页/共17页
{ if(up) { painter->drawPixmap(boundingRect().topLeft(),pix_up); up=!up; } else { painter->drawPixmap(boundingRect().topLeft(),pix_down); up=!up; }
}
第10页/共17页
第6页ቤተ መጻሕፍቲ ባይዱ共17页
7.2 图形视图示例
7.2.1 飞舞的蝴蝶例子
(1)新建Qt Gui应用,项目名为“Butterfly”,基类选择“QMainWindow”, 类名命名默认为“MainWindow”,取消“创建界面”复选框的选中状态。单击 “下一步”按钮,最后单击“完成”按钮,完成该项目工程的建立。
QRectF Butterfly::boundingRect() const {
qreal adjust =2; return QRectF(-pix_up.width()/2-adjust,-pix_up.height()/2-adjust,
pix_up.width()+adjust*2,pix_up.height()+adjust*2); }
#include <QApplication> #include "butterfly.h" #include <QGraphicsScene>
Qt动画效果的实现,QPropertyAnimation
Qt动画效果的实现,QPropertyAnimation Qt动画架构中的主要类如下图所⽰:动画框架由基类QAbstractAnimation和它的两个⼉⼦QVariantAnimation和QAnimationGroup组成。
QAbstractAnimation是所有动画类的祖宗。
它包含了所有动画的基本属性。
⽐如开始,停⽌和暂停⼀个动画的能⼒。
它也可以接收时间改变通知。
动画框架⼜进⼀步提供了QProertyAnimation类。
它继承⾃QVariantAnimation并对某个Qt属性(它须是Qt的”元数据对象系统”的⼀部分,见/nkmnkm/article/details/8225089)执⾏动画。
此类对属性执⾏⼀个宽松曲线插值。
所以当你想去动画⼀个值时,你可以把它声明为⼀个属性,并且让你的类成为⼀个QObject。
这给予我们极⼤的⾃由度来动画那些已存在的widget和其它QObject。
复杂的动画可以通过建⽴⼀个QAbstractAnimation的树来构建。
这个树通过使⽤QAnimationGroups来创建,QAnimationGroups作为其它动画的容器。
注意动画组也是从QAbstractAnimation派⽣的,所以动画组可以再包含其它动画组。
动画框架可以单独使⽤,同时也被设计为状态机框架的⼀部分。
状态机提供了⼀个特定的状态可以⽤来播放动画。
在进⼊或退出某个状态时QState也可以设置属性们,并且这个特定的动画状态将在指定QPropertyAnimation时给予的值之间做插值运算。
后⾯我们要进⼀步介绍此问题。
在场景的背后,动画被⼀个全局定时器收集,这个定时器发送update到所有的正在播放的动画中。
动画框架中的类们QAbstractAnimation 所有动画类的基类QAnimationGroup 动画组的基类QEasingCurve 控制动画的宽松曲线类QParallelAnimationGroup 并⾏动画组类QPauseAnimation 串⾏动画组类的暂停类QPropertyAnimation 动画Qt属性的类QSequentialAnimationGroup 串⾏动画组类QTimeLine 控制动画的时间线类QVariantAnimation 各动画类的虚基类动画Qt属性们如前⾯所讲,QPropertyAnimation类可以修改Qt属性们。
Qt动画框架
Qt动画框架状态机框架提供了创建和执行状态图的一些类.这些概念和表示都是基于Harel状态图中的一些概念和记法.它也是UML状态图表的基础.状态机执行的语义是基于状态图XML(SCXML).状态图提供了一种图形化的方式来对一个系统建模,从而反映它怎么响应外部触发.这是通过定义系统可能进入的一些状态以及系统怎么从一个状态转换到另一个状态(不同状态之间转变)来实现的.事件驱动系统的一个关键的特征(例如Qt应用程序)就是行为通常不仅取决于上次或当前事件,还取决于在它之前的一些事件.用状态图,这个信息非常容易表达.状态机框架提供了一套API以及一种执行模型,可有效地将状态图的元素和语义嵌入到Qt应用程序当中.该框架与Qt的元对象系统结合紧密:例如,不同状态之间的转变可由信号触发且状态可配置用于设置QObject的属性和方法.Qt的事件系统用于驱动状态机.状态机框架中的状态图是分层的.状态可嵌套在另一个状态内.状态机的当前配置包含一些当前活跃的状态.状态机中的一个有效的配置中的所有状态都有一个共同的祖先.状态机框架中的类qt提供了这些类来创建事件驱动的状态机.一个简单的状态机为了演示状态机API的核心功能,让我们来看一个小例子:一个状态机有三个状态s1,s2和s3.状态机由一个按钮来控制;当点击按钮时,状态机转换到另一个状态.刚开始时,状态机处于状态s1.该状态机的状态图如下所示:下面代码段显示了创建一个这样的状态机所需的代码.首先,我们创建一个状态机和一些状态:QStateMachine machine;QState *s1 = new QState();QState *s2 = new QState();QState *s3 = new QState();然后,我们使用QState::addTransition()函数创建转换:s1->addTransition(button, SIGNAL(clicked()), s2);s2->addTransition(button, SIGNAL(clicked()), s3);s3->addTransition(button, SIGNAL(clicked()), s1);接下来,我们将这些状态加入状态机中并设置它的初始状态:machine.addState(s1);machine.addState(s2);machine.addState(s3);machine.setInitialState(s1);最后,我们启动状态机:machine.start();状态是异步执行的,例如,它成为你的应用程序事件循环的一部分.在状态入口和出口做有意义的工作上面的状态机仅仅从一个状态转换到另一个状态,并没有执行任何操作.QState::assignProperty()函数可用于当进入某个状态时设置某个QObject的一个属性.在下面的代码段中,为每个状态指定了应当赋给QLabel的text属性的值.s1->assignProperty(label, "text", "In state s1");s2->assignProperty(label, "text", "In state s2");s3->assignProperty(label, "text", "In state s3");当进入了这些状态中的任何一个,标签的值就会相应地改变.当进入某个状态时,就会发出QState::entered()信号.当离开这个状态时,就会发出QState::exited()信号.在下面的代码段中,按钮的showMaximize()槽在进入状态s3时被调用.当退出状态s3时调用showMinimized():QObject::connect(s3, SIGNAL(entered()), button, SLOT(showMaximized()));QObject::connect(s3, SIGNAL(exited()), button, SLOT(showMinimized()));自定义的状态可以重新实现方法QAbstractState::onEntry()和QAbstractState::onExit().完成的状态机前面部分定义的状态机从不完成.为了使一个状态机能够完成,它需要拥有一个顶层的最终状态(QFinalState对象).当状态机进入一个顶层最终状态时,该状态机将会释放QStateMachine::finished()信号并停止.在图中引入一个最终状态,所有你需要做的就是创建一个QFinalState对象且使用它作为一个或多个转换的目标.通过对状态进行分组来共享转换假设我们想让用户能够通过点击Quit揿钮在任何时刻能够退出应用程序.为了完成这个目标,我们需要创建一个最终状态并将其作为与Quit按钮的clicked()信号相关联的转换的目标.我们可以从状态s1,s2,s3中添加一个转换;但是,这看起来像是多余的,并且,我们不得不记住从每个将来新加入的状态添加一个这样的转换.我们可以通过将状态s1,s2,s3分组取得相同的行为(即点击Quit 按钮将退出状态机,无论该状态机处于哪个状态).这是通过创建一个新的顶层状态并使三个原先的状态成为新状态的孩子.如下图显示了新状态机.三个原先的状态已经重命名为s11,s12和s13以反映它们现在已经是新的顶层状态s1的孩子.孩子状态隐含地继承它们的父状态的转换.这意味着现在增加一个从状态s1到最终状态s2的转换已经足够了.新加入s1的状态也将自动继承这个转换.将状态分组的所有工作就是当创始状态时,指定合适的父状态.你也需要指定哪个子状态是初始状态(例如,哪个子状态将是进入父状态时应该处于的状态).QState *s1 = new QState();QState *s11 = new QState(s1);QState *s12 = new QState(s1);QState *s13 = new QState(s1);s1->setInitialState(s11);machine.addState(s1);QFinalState*s2 = new QFinalState();s1->addTransition(quitButton, SIGNAL(clicked()), s2);machine.addState(s2);QObject::connect(&machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit()));在本例子中,我们想让状态机完成后,应用程序退出,因此状态机的finished()信号连接到应用程序的quit()槽.一个子状态可以覆盖一个继承过来的转换.例如,如下代码添加了一个转换,它有效地造成了当状态机处于状态s12时,Quit按钮将被忽略.s12->addTransition(quitButton, SIGNAL(clicked()), s12);一个转换可以将任何状态作为它的目标,例如,目标状态不一定要与源状态处于相同的层次.使用历史状态来保存和恢复当前状态假设我们要增加一个“中断”机制到前面提到的例子当中;用户应该能够点击一个按钮使状态机执行一些不相关的任务,任务完成后状态机应该能够恢复到之前执行的任何任务。
qt动画
Graphics View坐标系
• Graphics View基于笛卡尔坐标系。item在场 景中的位置与几何形状通过x,y坐标表示。 当使用未经变形的视图来观察场景时,场 景中的一个单位等于屏幕上的一个像素。 在Graphics View中有三个有效的坐标系统: Item坐标系,场景坐标系,视图坐标系。为 了简化你的实现,Graphics View提供了方便 的函数,允许三个坐标系之间相互映射。
不停闪烁的圆
自定义QGraphicsItem: class FlashItem : public QGraphicsItem , QObject { public: FlashItem(); //声明闪烁项目类的构造函数 QRectF boundingRect() const; //边界 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); //声明了重画函数,填充圆中颜色。 void timerEvent(QTimerEvent *); //声明定时器函数。 private: bool flash; //布尔型变量flash作为颜色切换的标志。 QTimer *timer; };
小结
QGraphicsScene是QGraphicsItem画布,把众 多的QGraphicsItem整合在一起。而 QGraphView则是 QGraphicsScene显示层, 即QGraphicsScene完成了“概念上”的显示 元素的设计,而QGraphicsView则是一种窗 口元 素,它完成了显示元素的显示,相当 于照相机的取景框,这个取景框可以覆盖 整个场景,也可以是场景的一部分。
Graphics Item变形
Qt-4.6Animation动画实现之状态机
Qt-4.6Animation动画实现之状态机状态机顾名思义,应该有不同的状态在切换。
上面状态机图中,我们提供了两种状态state1和state2。
而状态的区分是由状态的属性来描述的,比如p1,p2…等等。
从一个状态到另一个状态的转化,必须由触发条件来完成,上图state1到state2的状态转换由transition1来表示,state2到state1的状态转换由transition2来表示。
如果希望在状态转换过程中有动画来展示,那么可以在transition1和transition2中加入动画效果animation1和animation2 。
最后,状态机进入需要有一个初始状态,我们可以设定state1为我们这个状态机的初始态。
有了状态机的描述图,我们就可以看看用Qt-4.6的代码,如何实现以上功能。
#include<QtGui/QApplication>#include<QApplication>#include<QWidget>#include<QPushButton>#include<QStateMachine>#include<QState>#include<QSignalTransition>#include<QPropertyAnimation>int main(int argc,char*argv[]){QApplication app(argc,argv);QPushButton*button=new QPushButton("AnimatedButton");button->show();//创建状态机QStateMachine*machine=new QStateMachine;//创建两个状态,状态的属性由QPushButton的位置大小决定。
//QState*state1=new QState(machine->rootState());QState*state1=new QState(machine);state1->assignProperty(button,"geometry",QRect(480,480, 150,30));//QState*state2=new QState(machine->rootState());QState*state2=new QState(machine);state2->assignProperty(button,"geometry",QRect(250,250, 150,30));//将状态1设置为状态机的初始状态machine->setInitialState(state1);//增加触发状态1到状态2的触发条件,QPushButton按钮被按下,动画效果由addAnimation()完成/*细心的读者可能发现QPropertyAnimation的setStartValue()和setEndValue()都没有被调用到。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Graphics View的坐标系统
3.图形项坐标
QGraphicsItem类的坐标系,若在调用QGraphicsItem类的paint()函数重绘图元 时,则以此坐标系为基准。它的坐标都以点(0,0)为中心点,这也是所有变换的中 心点。 图形项位置指的是图形项的中心点在它父亲的坐标系中的坐标。如无父亲图 形项,则选场景坐标系。以这种思想来看,场景指的就是那些祖先最少的图形项 的“父亲”。最上级的图形项位置就是在场景中的位置。 子图形项会随着父图形项的变换而变换。(一起缩放,一起旋转等)。
e
Graphics View的坐标系统
2.视图坐标
QGraphicsView类继承自QWidget类,因此它与其他的QWidget类一样,以窗口 的左上角作为自己坐标系的原点,如图所示。 视图坐标是widget的坐标,视图坐标中每个单位对应一个像素。这种坐标的 特殊之处在于它是相对于widget或是视口的,不会被所观察的场景所影响。 QGraphicsView的视口的左上角总是(0,0),右下角总是(视口宽,视口高)。 所有的鼠标事件与拖拽事件,最初以视图坐标表示,需要把这些坐标映射到场景 坐标以便与图形项交互。
Graphics View的坐标系统
1.场景坐标
QGraphicsScene类的坐标系以中心为原点(0,0),如图所示。 场景坐标系统描述了每个最顶级图形项的位置,也是从视图向场景投递场景 事件的基础。场景中的每个图形项有场景位置与包围矩形 (QGraphicsItem ::scenePos(), QGraphicsItem::sceneBoundingRect()), 另外,它有 自己本地图形项位置与包围矩形。场景位置描述了图形项在场景坐标下的位置, 它的场景包围矩形则用于QGraphicsScene决定场景中哪块区域发生了变化。场景 中的变化通过QGraphicsScene::changed ()信号来通知,它的参数是场景矩形列表。
图形效果
QGraphicsEffect 是所有图形效果的基类。通过在源对象(如一个图形项)和目标 设备(如视图的视口)之间过节了渲染管道和一些操作来实现图形效果,Qt提供 了如下4个标准的图形效果: 模糊效果 QGraphicsBlurEffect 染色效果 QGraphicsColorizeEffect 阴影效果 QGraphicsDropShadowEffect 透明效果 QGraphicsOpacityEffect 使用方法: 先创建一个图形效果对象,再调用setGraphicsEffect()即可。 QGraphicsBlurEffect * blurEffect = new QGraphicsBlurEffect; blurEffect->setBlurHints(QGraphicsBlurEffect::QualityHint); blurEffect->setBlurRadius(8); setGraphicsEffect(blurEffect); 停止效果使用setEnabled(false) 【返回所用图形效果:QGraphicsEffect * QGraphicsItem::graphicsEffect() const】
小结
QGraphicsScene相当于画布,把众多的QGraphicsItem整合在一起。 而QGraphView则是QGraphicsScene显示层,即QGraphicsScene完成了 “概念上”的显示元素的设计,而QGraphicsView则是一种窗口元素,它 完成了显示元素的显示,相当于照相机的取景框,这个取景框可以覆盖 整个场景,也可以是场景的一部分。
使用advance()实现动画
可以使用QGraphicsScene::advance()来推进场景,定时器timeout()信号和场景的 advance()槽关联。 QTimer timer; QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance())); timer.start(1000 / 33); 场景的advance()槽执行时会调用每个图形项的advance()函数(不是槽)。所以只需 要重写每个图形项的advance()函数即可。 void Mouse::advance(int step) { if (!step) return; ... }
int main(int argc, char * argv[]) { QApplication app(argc, argv); QGraphicsScene scene; QGraphicsRectItem * item = new QGraphicsRectItem(0,0,100,100); scene.addItem(item); QTransform transform; qDebug() << scene.itemAt(50.,50., transform); return app.exec(); }
view.setForegroundBrush(QColor(255,255,255,100)); view.setBackgroundBrush(QPixmap(":/Desert.jpg")); view.resize(400,300); view.show();
return app.exec(); }
可自定义新的图形项 注:Item的绘制是基于它本身的局部坐标系的。
支持如下功能: 鼠标按下、移动、释放、双击、悬停、滚轮、右键菜单 键盘输入焦点和键盘事件 拖放事件 父子图形项 分组,通过QGraphicsItemGroup 支持自定义数据,setData(), data()
自定义图形项
class MyItem : public QGraphicsItem { public: MyItem(); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); }; QRectF MyItem::boundingRect() const { qreal penWidth = 1; return QRectF(0-penWidth/2., 0-penWidth/2., 20+penWidth, 20 + penWidth); } void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->setBrush(Qt::red); painter->drawRect(0,0,20,20); }
Graphics View坐标系
Graphics View基于笛卡尔坐标系。item在场景中的位置与几何形状通 过(x,y)坐标表示。当使用未经变形的视图来观察场景时,场景中的一个 单位等于屏幕上的一个像素。在Graphics View中有三个有效的坐标系统: 图形项坐标系,场景坐标系,视图坐标系。为了简化实现,Graphics View提供了方便的函数,允许三个坐标系之间相互映射。
QGraphicsScene 表示Graphics View中的场景,它有以下职责:
• 为管理大量的图形项提供一个快速的接口。 • 传播事件到每个图形项。 • 管理图形项的状态,例如选择,焦点处理。 • setSelectionArea(), selectedItems(), setFocusItem()等 • 提供未经变换的渲染功能,主要用于打印。 • render() • 场景作为QGraphicsItem对象的容器。通过调用 QgraphicsScene::addItem()把图形项加入到场景中。 • 可以使用众多的查找函数来获取特定的图形项。 • items(), itemAt()
Graphics View的坐标系统
Graphics View框架提供了多种坐标变换函数:
自定义视图、三种坐标关系
class MyView : public QGraphicsView { public: MyView(); protected: void mousePressEvent(QMouseEvent *); }; void MyView::mousePressEvent(QMouseEvent * event) { QPoint viewPos = event->pos(); qDebug() << "viewPos: " << viewPos; QPointF scenePos = mapToScene(viewPos); qDebug() << "scenePos: " << scenePos; QGraphicsItem * item = scene() ->itemAt(scenePos, QTransform()); if ( item ) { QPointF itemPos = item -> mapFromScene(scenePos); qDebug() << "itemPos: " << itemPos; } }
注意:此处的(0,0,100,100)表示图形项的坐标,不是在场景中的位置
QGraphicsView(视图)
QGraphicsView提供了视图部件,用来可视化场景中的内容。可以联 结多个视图到同一个场景,对这个相同的数据集提供几个视口。视口部 件是一个滚动区域,它提供了滚动条以对大场景进行浏览。 setDragMode(): ScrollHandDrag, RubberBandDrag setViewport(): QGLWidget可支持OpenGL渲染