使用QPushButton、QLabel、QCheckBox等构成GUI的控件或自定义图形时,开发应用程序会变得很简单。
但是如果想在GUI中使用数十个或者数百个图形对象,向用户完美展示控制场景,则会受到很多的限制。
使用Qt图形视图框架用来管理2D图形项,支持绘制、缩放、事件响应等等。
1、快速提供并管理大量对象
2、将事件传递到每一个对象
3、管理焦点处理或对象选择等状态
在需要大量图元绘制时为什么要使用Qt的图形试图框架呢?因为效率高!那为什么效率高,效率又有多高呢?
答案就是QGraphicsView框架通过二元空间划分树(Binary Space Partitioning,BSP)提供快速的图元查找,这样就能够实时地显示包含上百万个图元的大场景了。
在Qt图形视图中起主要作用的3个类:,分别是QGraphicsView(视图),QGraphicsSence(场景),QGraphicsItem(图元);
QGraphicsView : 间接继承于QWidget,既然是继承于Ui类。
QGraphicsSence:一个用来容纳图元的容器。
QGraphicsItem : 所有图元的基类。
三者关系:QGraphicsItem是图形的抽象;QGraphicsSence用来容纳QGraphicsItem对象的容器,但是无法显示图元,只有依赖QGraphicsView才能显示图元。
下面代码以一个最简单的例子来演示三者之间的关系:
蝴蝶飞舞
#include <QApplication>
#include "butterfly.h"
#include <QGraphicsScene>
#if 0
结构总结:
①继承QGraphicsItem生成了一个可自我维护的图元。
②生成场景,设置场景大小。
③生成QGraphicsView用于对场景进行显示。
#endif
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene *scene = new QGraphicsScene;
//确定scene的大小 四个参数依次是:x起点,y起点 长度 宽度
scene->setSceneRect(QRectF(-200,-200,400,400));
//继承于QGraphicsItem
Butterfly *butterfly = new Butterfly;
butterfly->setPos(-100,0);
scene->addItem(butterfly);
QGraphicsView *view = new QGraphicsView;
view->setScene(scene);
view->resize(1920,1080);
view->show();
return a.exec();
}
butterfly.h
#ifndef BUTTERFLY_H
#define BUTTERFLY_H
#include <QObject>
#include <QGraphicsItem>
#include <QPainter>
#include <QGraphicsScene>
#include <QGraphicsView>
class Butterfly : public QObject,public QGraphicsItem
{
Q_OBJECT
public:
explicit Butterfly(QObject *parent = 0);
//一个被重写的虚函数,可以使用startTimer(100)启动
void timerEvent(QTimerEvent *);
QRectF boundingRect() const;
signals:
public slots:
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
private:
bool up;
QPixmap pix_up; //用于表示两幅蝴蝶的图片
QPixmap pix_down;
qreal angle;
};
#endif // BUTTERFLY_H
butterfly.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);
}
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;
}
}
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());
angle+=(qrand()%10)/20.0;
qreal dx=fabs(sin(angle*PI)*10.0);
qreal dy=(qrand()%20)-10.0;
setPos(mapToParent(dx,dy));
}