1、QGraphicsView介绍
QT4.2开始引入了Graphics View框架用来取代QT3中的Canvas模块,并作出了改进,QGraphicsView框架实现了模型-视图结构的图形管理,能对大量图元进行管理,支持碰撞检测,坐标变换和图元组等多种方便的功能。
GraphicsView框架结构主要包含三个主要的类QGraphicsScene(场景)、QGraphicsView(视图)、QGraphicsItem(图元)。QGraphicsScene本身不可见,是一个存储图元的容器,必须通过与之相连的QGraphicsView视图来显示及与外界进行交互,主要提供图元的操作接口、传递事件和管理各个图元状态,提供无变换的绘制功能(如打印);QGraphicsView提供一个可视的窗口,用于显示场景中的图元,一个场景中可以有多个视图。QGraphicsItem是场景中各个图元的基础类,QT提供了常用图形图元的标准类,如矩形(QGraphicsRectItem)、椭(QGraphicsEllipseItem)、文本(QGraphicsTextItem)。
QGraphicsView是一个基于图元的Model/View架构的框架,每一个组件都是一个独立的元素。QPainter采用面向过程的描述方式绘图;QGraphicsView采用面向对象的描述方式绘图。GraphicsView绘图时首先创建一个场景,然后创建图元对象(如一个直线对象、一个多边形对象),再使用场景的add()函数,将图元对象添加到场景中,最后通过视图进行显示。对于复杂的图像来说,如果图像包含大量的直线、曲线、多边形等图元对象,管理图元对象比管理QPainter的绘制过程语句要容易,并且图元对象更符合面向对象的思想,图形的可复用性更好。
2、QGraphicsView的架构
QGraphicsView的架构中,主要涉及以下三种类的使用:
QGraphicsScene(场景类):该类提供了我们所需要的绘图场景,场景是不可见的,但是我们可以向场景中添加图元
QGraphicsView(视图类):该类提供了一些基本的图形元件,也可在此基础上自定义图形项,它支持各种事件的响应,如鼠标事件、键盘事件、拖放事件等,以实现图形的交互功能,下面列举一些标准图元:
- QGraphicsEllipseItem(椭圆)
- QGraphicsLineItem (直线)
- QGraphicsPathItem (路径)
- QGraphicsPixmapItem (图像)
- QGraphicsPolygonItem (多边形)
- QGraphicsRectItem (矩形)
- QGraphicsSimpleTextItem (文本)
- QGraphicsItem(图元的基类),我们可以创建一个图元类,让它继承于QGraphicsItem,实现自定义的图元。
3、坐标系统
QGraphicsView基于笛卡尔坐标系。item在场景中的位置与几何形状通过x,y坐标来表示。当使用未经变形的视图来观察场景时,场景中的一个单位等于屏幕上的一个像素。在QGraphicsView绘图架构中涉及到了3个坐标系,即场景坐标、视图坐标及图形项坐标。
场景坐标:对应QPainter的逻辑坐标,以场景的中心为原点,X轴正方向向右,Y轴正方向向下,如下图所示:
视图坐标:即窗口界面的物理坐标,单位是像素,其左上角为原点坐标,所有鼠标事件、拖拽事件最开始都使用视图坐标,为了和图元交互,需要转换坐标为场景坐标。
图形项坐标:图元存在于自己的本地坐标上,通常以图元的中心为原点,图元中心也是所有坐标变换的原点,图元坐标方向是X轴正方向向右,Y轴正方向向下(同上图)。
4、测试案例
#include "Widget.h"
#include <QtWidgets/QApplication>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QGraphicsRectItem>
#include<QGraphicsSimpleTextItem>
#include<QGraphicsLineItem>
#include<QGraphicsPolygonItem>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//创建场景
QGraphicsScene scene;
scene.setBackgroundBrush(QBrush(QColor(160, 50, 45)));
//创建画笔
QPen pen;
pen.setWidth(5);
pen.setBrush(QBrush(Qt::yellow));
//创建矩形图元
QGraphicsRectItem* rect = new QGraphicsRectItem();
rect->setRect(QRectF(100, 150, 100, 100));
rect->setPen(pen);
rect->setBrush(QBrush(Qt::red));
rect->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
//创建直线图元
QGraphicsLineItem* line = new QGraphicsLineItem();
line->setLine(QLineF(50, 50, 130, 80));
line->setPen(pen);
line->setFlag(QGraphicsItem::ItemIsMovable);
//创建一个多边形图元
QGraphicsPolygonItem* polygon_item = new QGraphicsPolygonItem();
QPolygonF poly;
poly << QPointF(200, 300) << QPointF(300, 300) << QPointF(360, 400) << QPointF(200, 400);
polygon_item->setPolygon(poly);
polygon_item->setPen(pen);
polygon_item->setFlag(QGraphicsItem::ItemIsMovable);
//创建文本图元
QGraphicsSimpleTextItem* text = new QGraphicsSimpleTextItem();
text->setPen(pen);
text->setText("hello world");
text->setFont(QFont("华文琥珀", 30));
text->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
scene.addItem(rect);
scene.addItem(line);
scene.addItem(text);
scene.addItem(polygon_item);
QGraphicsView view(&scene);
view.resize(1080, 720);
view.show();
Widget w;
w.resize(1080, 720);
w.show();
return a.exec();
}
测试代码的效果如下: