作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
简介
在Qt界面库中,对于图形的绘制,可以使用 QPainter 实现普通二维图形的绘制,该方法在 paintEvent 事件里编写绘图程序,其本质绘制的图形是位图,这种方法更适合于绘制复杂度不高的固定图形,并且不能实现图项的选择、编辑、拖放、修改等交互功能。
对于需要绘制大量的、需要交互的图形,可使用Graphics View绘图架构,它是一种基于图形项(Graphics Item)的模型/视图模式,这种方式可以在一个场景中绘制大量图元项,且每个图元项都是可选择、可交互的。
从QT4.2开始引入了Graphics View框架用来取代QT3中的Canvas模块,并作出了改进,Graphics View框架实现了模型-视图结构的图形管理,能对大量图元进行管理,支持碰撞检测,坐标变换和图元组等多种方便的功能。
QPainter采用面向过程的描述方式绘图;GraphicsView采用面向对象的描述方式绘图。对于复杂的图像来说,如果图像包含大量的直线、曲线、多边形等图元对象,管理图元对象比管理QPainter的绘制过程语句要容易,并且图元对象更符合面向对象的思想,图形的可复用性更好。
GraphicsView 框架
在Graphics View绘图架构中,主要涉及到下面三个类的使用:
- 场景类(QGraphicsScene):该类提供绘图场景(Scene),场景是不可见的,是一个抽象的管理图形项的容器,可向场景中添加图形项,获取场景中的某个图形项等,主要功能如下:
- 提供管理大量图元的快速接口;
- 传播事件到场景中的每个图元;
- 提供未经变换的渲染功能,主要用于打印;
- 管理图元状态,如图元选择和焦点处理;
-
视图类(QGraphicsView):该类提供绘图的视图(View)组件,用于显示场景中的内容。可以为一个场景设置几个视图,用于对同一个数据集提供不同的观察方式;
-
图形项类(QGraphicsItem):该类提供了一些基本的图形元件,也可在此基础上自定义图形项,它支持各种事件的响应,如鼠标事件、键盘事件、拖放事件等,以实现图形的交互功能,下面列举一些标准图元:
- QGraphicsEllipseItem 椭圆
- QGraphicsLineItem 直线
- QGraphicsPathItem 路径
- QGraphicsPixmapItem 图像
- QGraphicsPolygonItem 多边形
- QGraphicsRectItem 矩形
- QGraphicsSimpleTextItem 简单文本
- QGraphicsTextItem 文本浏览
- QGraphicsItem是图元的基类,用户可以继承QGraphicsItem实现自定义的图元;
GraphicsView 坐标系
Graphics View基于笛卡尔坐标系。item在场景中的位置与几何形状通过x,y坐标来表示。当使用未经变形的视图来观察场景时,场景中的一个单位等于屏幕上的一个像素。在Graphics View绘图架构中涉及到了3个坐标系,即场景坐标、视图坐标及图形项坐标。
- 场景坐标:对应QPainter的逻辑坐标,以场景的中心为原点,X轴正方向向右,Y轴正方向向下;
- 视图坐标:即窗口界面的物理坐标,单位是像素,其左上角为原点坐标,所有鼠标事件、拖拽事件最开始都使用视图坐标,为了和图元交互,需要转换坐标为场景坐标;
- 图形项坐标:图元存在于自己的本地坐标上,通常以图元的中心为原点,图元中心也是所有坐标变换的原点,图元坐标方向是X轴正方向向右,Y轴正方向向下(同上图)。
示例
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include "math.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene; // 定义一个场景,设置背景色为红色
scene.setBackgroundBrush(Qt::red);
QPen pen; // 定义一个画笔,设置画笔颜色和宽度
pen.setColor(QColor(0, 160, 230));
pen.setWidth(10);
QGraphicsRectItem *m_rectItem = new QGraphicsRectItem(); // 定义一个矩形图元
m_rectItem->setRect(0, 0, 80, 80);
m_rectItem->setPen(pen);
m_rectItem->setBrush(QBrush(QColor(255, 0, 255)));
m_rectItem->setFlag(QGraphicsItem::ItemIsMovable);
QGraphicsLineItem *m_lineItem = new QGraphicsLineItem(); // 定义一个直线图元
m_lineItem->setLine(QLineF(0, 0, 100, 100));
m_lineItem->setPen(pen);
m_lineItem->setFlag(QGraphicsItem::ItemIsMovable);
QGraphicsPathItem *m_pathItem = new QGraphicsPathItem(); // 定义一个路径图元
QPainterPath path;
path.moveTo(90, 50);
for (int i = 1; i < 5; ++i) {
path.lineTo(50 + 40 * cos(0.8 * i * M_PI), 50 + 40 * sin(0.8 * i * M_PI));
}
path.closeSubpath();
m_pathItem->setPath(path);
m_pathItem->setPen(pen);
m_pathItem->setFlag(QGraphicsItem::ItemIsMovable);
QGraphicsPolygonItem *m_polygonItem = new QGraphicsPolygonItem(); // 定义一个多边形图元
QPolygonF polygon;
polygon << QPointF(-100.0, -150.0) << QPointF(-120.0, 150.0)
<< QPointF(320.0, 160.0) << QPointF(220.0, -140.0);
m_polygonItem->setPolygon(polygon);
m_polygonItem->setPen(pen);
m_polygonItem->setFlag(QGraphicsItem::ItemIsMovable);
scene.addItem(m_rectItem); // 把矩形图元添加到场景
scene.addItem(m_lineItem); // 把直线图元添加到场景
scene.addItem(m_pathItem); // 把路径图元添加到场景
scene.addItem(m_polygonItem); // 把多边形图元添加到场景
QGraphicsView view(&scene); // 定义一个视图,并把场景添加到视图
view.resize(1024, 768);
view.show();
return a.exec();
}