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();

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值