Qt5开发学习之图形视图框架(九)
图形视图体系结构
- Graphics View框架结构主要特点:
- 1、系统可以利用Qt的反锯齿、OpenGL工具来改善绘图性能。
2、Graphics View支持事件传播体系结构,可以使图元在场景(scene)中的交互能力提升一倍,图元能够处理鼠标事件和键盘事件。
3、在框架中,可以通过二元空间划分树提供快速的图元查找,这样就能实时的显示包含上百万个图元的大场景
- Graphics View的三元素:
-
1、场景类:
QGraphicsScene
类是一个用于放置图元的容器,本身是不可见的,必须通过与之相连的视图类来显示及与外界进行交互操作。通过QGraphicsScene::addItem()
添加一个图元文件到场景中。QGraphicsScene::items()
和一些重载函数可以返回各种形状的所有图元。QGraphicsScene::itemAt()
返回指定点最顶层的图元。场景类主要的功能包括:提供对它包含的图元的操作接口和传递事件、管理各个图元的状态(如选择和焦点处理)、提供无变换的绘制功能(如打印):
事件传播体系结构将场景事件发送给图元,同时也管理图元之间的事件传播。
管理各个图元的状态可以通过
QGraphicsScene::setSelectionArea()
函数选择图元,选择区域可以使任意形状,使用QPainterPath
表示。若要的当前选择的图元列表,则可以使用QGraphicsScene::selectedItems()
。设置图元的焦点可以使用QGraphicsScene::setFocus()
和QGraphicsScene::setFocusItem()
函数,获得当前具有焦点的图元使用QGraphicsScene::focusItem()
。使用
QGraphicsScene::render()
函数将场景内容绘制到特定的设备上。
2、视图类:
QGraphicsView
提供一个可视的窗口用于显示场景中的图元。在同一个场景中可以有多个视图,也可以为相同的数据集提供几种不同的视图。QGraphicsView是可滚动的窗口部件,可以提供滚动条来浏览大的场景。如果需要使用OpenGL,可以使用
QGraphicsView::setViewport()
将视图设置为QGLWidget
。视图接收鼠标和键盘的输入事件,并将它们翻译为场景事件(将坐标转换为场景的坐标),使用变换矩阵函数
QGraphicsView::matrix()
可以变换场景的坐标,实现场景的缩放和旋转。QGraphicsView::mapToScene()
和QGraphicsView::mapFromScene()
用于与场景的坐标进行互相转换。
3、图元类:
QGraphicsItem
是场景中各个图元的基类,在它的基础上可以继承出各种图元类。图元类主要的功能有:
- 处理鼠标的各种事件;
- 处理键盘输入事件;
- 处理拖曳事件;
- 分组;
- 碰撞检测;
图元也有自己的坐标系,也提供场景和图元,还可以包含子图元。
- GraphicsView的坐标系统
-
三个GraphicsView基本类有各自不同的坐标系,场景坐标、视图坐标和图元坐标。在绘制图形时,GraphicsView的场景坐标对应QPainter的逻辑坐标、视图坐标和设备坐标。
场景坐标是所有图元的基础坐标系统,描述了顶层的图元,没个图元都有场景坐标和相应的包容框;
视图坐标是窗口部件的坐标,单位是像素。以窗口左上角作为坐标系的原点。
图元坐标使用自己的本地坐标,这个坐标系统通常以图元中心为原点,这也是所有变换的原点。
图形视图
实例:制作动画
首先制作一个图元,通过定时器不停改变图元的显示。再将图元加载到场景中:
图元的制作:
#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QPainter>
class Butterfly : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit Butterfly(QObject *parent = 0);
// 在定时器函数timerEvent()对QGraphicsItem进行重绘,实现动画
void timerEvent(QTimerEvent *event);
// 图元限定区域范围,所有继承自QGraphicsItem的自定义图元都要实现此函数
QRectF boundingRect() const;
signals:
public slots:
// 重绘函数
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
private:
bool up; // 用于标志蝴蝶翅膀的位置,实现动画
QPixmap pix_up;
QPixmap pix_down;
qreal angle;
};
cpp:
#include "Butterfly.h"
#include <math.h>
const static double PI = 3.1416;
Butterfly::Butterfly(QObject *parent) : QObject(parent)
{
up = true;
pix_up.load("up.png");
pix_down.load("down.png");
startTimer(100);
}
void Butterfly::timerEvent(QTimerEvent *)
{
// 边界控制
// 限定蝴蝶的右边界
qreal edgex = scene()->sceneRect().right() + boundingRect().width() / 2;
// 限定蝴蝶上边界
qreal edgetop = scene()->sceneRect().top() + boundingRect().height() / 2;
// 限定蝴蝶下边界
qreal edgebottom = scene()->sceneRect().bottom() + boundingRect().height() / 2;
// 若超过了右边界则水平移回左边界
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());
}
// dx,dy完成蝴蝶随机飞行路径
angle += (qrand() % 10) / 20.0;
qreal dx = fabs(sin(angle * PI) * 10.0);
qreal dy = (qrand() % 20) - 10.0;
setPos(mapToParent(dx, dy));
}
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);
}
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;
}
}
主函数中加载场景:
“`cpp
include
include “Butterfly.h”
include
// 完成了图元的设计,将它加载进场景中
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene *scene = new QGraphicsScene;
scene->setSceneRect(-100, -100, 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();
}
下一篇: JS学习(JS函数知识)
推荐阅读