Graphics View 的特点

  • Graphics View框架结构中,系统可以利用Qt绘图系统的反锯齿、OpenGL工具来改善绘图性能;
  • Graphics View支持事件传播体系结构,可以使图元在场景(scene)中的交互能力提高1倍,图元能够处理键盘事件和鼠标事件。其中,鼠标事件包括鼠标按下、移动、释放和双击,还可以跟踪鼠标的移动;
  • 在Graphics View框架中,通过二元空间划分树提供快速的图元查找,这样就能够实时地显示包含上百万个图元的大场景。

Graphics View 的三元素

  • 场景类(QGraphicsScene)

    场景类提供了一个用于管理位于其中的众多图元的容器。场景类本身是不可见的,必须通过与之相连的视图类来显示及与外界进行交互操作。

    场景类的常用操作如下:

    • QGraphicsScene::addItem():添加一个图元到场景中
    • QGraphicsScene::items():返回场景中所以图元;
  • QGraphicsScene::itemAt():返回指定点的顶层图元;

  • 视图类(QGraphicsView) 视图类用于显示场景中的图元,一个场景可以通过多个视图表现,也可以为相同的数据集提供几种不同的视图。

  • 图元类(QGraphicsItem) 图元类是场景中各个图元的基类,在它的基础上可以继承出各种图元类。Qt中已经预置了如下图元:直线图元(QGraphicsLineItem)、椭圆图元(QGraphicsEllipseItem)、文本图元(QGraphicsTextItem)、矩形图元(QGraphicsRectItem)等。当然用户可以继承QGraphicsItem实现符合自己需要的图元。  QGraphicsItem主要有以下几点功能:  1.处理鼠标按下、移动、释放、双击、悬停、滚轮、和右键菜单事件;  2.处理键盘输入事件;  3.处理拖拽事件;  4.分组;  5.碰撞检测。

Graphics View 的坐标系统

​ Graphics View坐标是基于笛卡尔坐标系,三个Graphics View基本类有各自不同的坐标系。当然Graphics View提供了三个坐标系统之间的转换函数。

视图(QGraphicsView)的坐标

​ 视图将窗口中的左上角作为原点(0,0),不弄窗口大小,原点总是在左上角。向右为X轴正方向,向下为Y轴正方向。如下图所示: 视图坐标示意

场景坐标

场景坐标是所有图元的基础坐标系统。通常情况下场景的坐标原点(0,0)在场景的的中心位置。向右为X轴的正方向,向下为Y轴的正方向,如下图所示: 场景坐标示意 通过void setSceneRect(qreal x, qreal y, qreal w, qreal h)函数可以设置场景的坐标以及大小。其中x和y用于设定场景左上角的坐标,w和h来设定场景的大小。

图元(QGraphicsItem)坐标

图元使用自己的本地坐标,这个坐标系统通常以(0,0)为原点,这也是所有变换的原点。图元坐标方向是X轴正方向向右,Y轴正方向向下。

void setPos(qreal x, qreal y)指定图元的原点在场景中的坐标。

void QGraphicsItem::setTransformOriginPoint(qreal x, qreal y)指定图元进行旋转等变换时的中心坐标

坐标变换函数

QGraphicsView框架提供了多种坐标变换函数,如下图所示: QGraphicsView坐标变换函数

GraphicsView 类型成员

1、QGraphicsView::CacheModeFlag:视图的缓存模式。视图可以在 QPixmap 中缓存预渲染的内容,然后将其绘制到视口上。这种缓存的目的是加快渲染速度较慢的区域的总渲染时间。例如,纹理、渐变和 alpha 混合背景的渲染速度可能非常慢,尤其是转换后的视图。 每次转换视图时,缓存都会失效。滚动时,只需要部分失效。

  • CacheNone:不缓存,所有绘制都直接在视口上完成。
  • CacheBackground:启用缓存背景。

2、QGraphicsView::DragMode:在视口上按下并拖动鼠标时视图的默认操作。

  • NoDrag:无拖拽,鼠标事件被忽略。
  • ScrollHandDrag:光标变为指向手型,拖动鼠标将滚动滚动条。 此模式在交互和非交互模式下均可使用。
  • RubberBandDrag:会出现一个橡皮筋框。拖动鼠标将设置橡皮筋框范围,所有被橡皮筋覆盖的项目都会被选中。对于非交互式视图禁用此模式。

3、QGraphicsView::OptimizationFlag:可以启用以提高视图渲染性能的标志。默认情况下,没有设置这些标志。设置标志通常会产生副作用,并且此效果可能在绘画设备和平台之间有所不同。

  • DontSavePainterState:渲染时,视图会在渲染背景或前景以及渲染每个图形项时保存画家状态(QPainter::save())。

  • DontAdjustForAntialiasing:禁用视图对暴露区域的抗锯齿自动调整。在QGraphicsItem::boundingRect() 边界上呈现抗锯齿线的图形项最终可能会在外部呈现部分线条。为了防止呈现伪像,视图将所有暴露区域在所有方向上扩大2个像素。 如果启用此标志,视图将不再执行这些调整,从而最小化需要重绘的区域,从而提高性能。一个常见的副作用是使用抗锯齿绘制的项目在移动时会在场景中留下绘画痕迹。

4、QGraphicsView::ViewportAnchor:当用户调整视图大小或转换视图时视图可以使用的锚点。

  • NoAnchor:没有锚点,即视图使场景的位置保持不变。
  • AnchorViewCenter:视图中心的场景点用作锚点。
  • AnchorUnderMouse:鼠标下方的点用作锚点。

5、QGraphicsView::ViewportUpdateMode:场景内容更改时如何更新视口。

  • FullViewportUpdate:当场景的任何可见部分发生变化或重新曝光时,视图将更新整个视口。这是不支持部分更新的视口(例如 QOpenGLWidget)以及需要禁用滚动优化的视口的首选更新模式。
  • MinimalViewportUpdate:视图将确定需要重绘的最小视区区域,通过避免重绘未更改的区域来最小化绘制时间。 这是视图的默认模式。虽然这种方法总体上提供了最好的性能,但如果场景中有许多小的可见变化,视图最终可能会花费更多的时间来寻找最小化区域的方法而不是绘制。
  • SmartViewportUpdate:视图将尝试通过分析需要重绘的区域来寻找最佳更新模式。
  • BoundingRectViewportUpdate:将重新绘制视口中所有更改的边界矩形。这种模式的优点是视图只搜索一个区域的变化,最大限度地减少确定需要重绘什么的时间。缺点是没有改变的区域也需要重新绘制
  • NoViewportUpdate:视图永远不会在场景改变时更新它的视口,用户应控制所有更新。此模式禁用视图中的所有(可能很慢)图形项可见性测试,适用于需要固定帧速率或视口以其他方式从外部更新的场景。

GraphicsView 属性成员

1、alignment : Qt::Alignment

​ 当整个场景可见时(即没有可见的滚动条(视图范围 >= 场景范围)),此属性保持视图中场景的对齐方式。对齐方式将决定场景在视图中的渲染位置。例如,如果对齐方式是Qt::AlignCenter,这是默认的,场景将在视图中居中,如果对齐方式是(Qt::AlignLeft | Qt::AlignTop),场景将在顶部渲染 - 视图的左角。

2、backgroundBrush : QBrush

​ 此属性保存场景的背景画刷。它用于覆盖场景自身的背景。要为视图提供自定义背景绘图,可以改为重新实现 drawBackground()。默认为 Qt::NoBrush 模式的画刷。

3、cacheMode : CacheMode

​ 缓存背景模式。如:

QGraphicsView view;
view.setBackgroundBrush(QImage(":/images/backgroundtile.png"));
view.setCacheMode(QGraphicsView::CacheBackground);

4、dragMode : DragMode

5、foregroundBrush : QBrush

​ 此属性保存场景的前景画刷。它用于覆盖场景自身的前景。要为视图提供自定义前景绘图,可以改为重新实现drawForeground()。默认为Qt::NoBrush模式的画刷。 6、interactive : bool

​ 视图是否允许场景交互。如果启用,此视图将设置为允许场景交互。否则不允许交互,并且将忽略任何鼠标或键事件(即,它将充当只读视图)。默认为 true。 7、optimizationFlags : OptimizationFlags

8、renderHints : QPainter::RenderHints

​ 这些提示用于在绘制每个可见图形项之前初始化QPainter。默认情况下启用QPainter::TextAntialiasing。例:

 QGraphicsScene scene;
 scene.addRect(QRectF(-10, -10, 20, 20));
 QGraphicsView view(&scene);
 view.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
 view.show();

9、resizeAnchor : ViewportAnchor

​ 调整视图大小时,视图应如何定位场景。

10、rubberBandSelectionMode : Qt::ItemSelectionMode

​ 使用橡皮筋框选择矩形选择图形项的行为。具体值见:QGraphicsScene详解 第42个成员函数。

11、sceneRect : QRectF

​ 视图可视化的场景区域。如果未设置,或者如果设置了空 QRectF,则此属性与QGraphicsScene::sceneRect 具有相同的值,并随 QGraphicsScene::sceneRect 更改。否则,视图的场景矩形不受场景影响。 12、transformationAnchor : ViewportAnchor

​ 视图在转换过程中应如何定位场景。 13、viewportUpdateMode : ViewportUpdateMode

三、成员函数

void invalidateScene(const QRectF &rect = QRectF(), QGraphicsScene::SceneLayers layers = QGraphicsScene::AllLayers)
// 使场景中的矩形rect内的图层无效并安排重绘。rect内图层的任何缓存内容都将无条件地失效并重新绘制。
    
[signal] void rubberBandChanged(QRect rubberBandRect, QPointF fromScenePoint, QPointF toScenePoint) 
// 当橡皮筋矩形改变时发出这个信号。橡皮筋矩形为rubberBandRect。参数2和参数3为拖动开始位置和拖动结束位置,都是场景中的点。当橡皮筋选择结束时,此信号将与空值一起发射。

void updateScene(const QList<QRectF> &rects)
// 立刻更新场景矩形。

void centerOn(const QPointF &pos)
// 滚动视口的内容以确保场景坐标pos在视图中居中。

void centerOn(const QGraphicsItem *item) 
// 滚动视口的内容以确保图形项在视图中居中。

void drawBackground(QPainter *painter, const QRectF &rect)
// 默认调用场景的 drawBackground()。
    
void drawForeground(QPainter *painter, const QRectF &rect) 
//默认调用场景的 drawForeground()。使用 viewport()->update() 刷新内容。
    
void ensureVisible(const QRectF &rect, int xmargin = 50, int ymargin = 50) 
//滚动视口的内容使场景矩形rect可见,边距由 xmargin 和 ymargin 以像素为单位指定。 如果无法到达指定的矩形,则将内容滚动到最近的有效位置。

void ensureVisible(const QGraphicsItem *item, int xmargin = 50, int ymargin = 50)
//滚动视口的内容使图形项可见。如果无法到达指定的图形项所在位置,则将内容滚动到最近的有效位置。
    
void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio) 
//缩放视图矩阵并滚动滚动条以确保场景矩形rect适合视口。rect必须在场景rect内,否则fitInView()不能保证整个矩形都是可见的。此函数只缩放和滚动滚动条但保持视图的旋转、平移或剪切。视图根据aspectRatioMode 进行缩放。
    gphv->fitInView(QRect(0,0,300,300));


void fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio)
//确保 item 紧密地适合视图,根据 aspectRatioMode 缩放视图。

QGraphicsItem * itemAt(const QPoint &pos) 
//返回位置 pos 处的图形项,pos在视口坐标中。如果此位置有多个图形项,则此函数返回最上面的图形项。
    
QList<QGraphicsItem *> items()
//返回关联场景中所有图形项的列表,按堆叠顺序降序排列。
    
QList<QGraphicsItem *> items(const QPoint &pos)
//返回视图中位置 pos 处所有图形项的列表。按堆叠顺序降序排列。pos在视口坐标中。
    
QList<QGraphicsItem *> items(const QRect &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape)
//包含在 rect 中或与 rect 相交的所有项目的列表。 rect 在视口坐标中。模式见:QGraphicsScene详解 第42个成员函数。项目按堆叠降序排序。
    
QList<QGraphicsItem *> items(const QPolygon &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape)
//重载函数。
    
QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape)
//重载函数。
    
QPoint mapFromScene(const QPointF &point) 
QPolygon mapFromScene(const QRectF &rect) 
QPolygon mapFromScene(const QPolygonF &polygon) 
QPainterPath mapFromScene(const QPainterPath &path) 
//场景坐标中的点、矩形、多边形、路径转换到视口坐标中的点、多边形、路径。
    
QPointF mapToScene(const QPoint &point) 
QPolygonF mapToScene(const QRect &rect) 
QPolygonF mapToScene(const QPolygon &polygon) 
QPainterPath mapToScene(const QPainterPath &path) 
//视图坐标转场景坐标。
    
void render(QPainter *painter, const QRectF &target = QRectF(), const QRect &source = QRect(), Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio) 
//使用painter将处于视图坐标中的 source 从场景渲染到处于绘制设备坐标中的 target 。如果 source 是一个空矩形,这个函数将使用viewport()->rect() 来确定要绘制的内容。 如果目标是空矩形,则将使用画家绘制设备的完整尺寸(例如,对于 QPrinter,页面大小)。源矩形内容将根据 aspectRatioMode 进行转换以适应目标矩形。 默认情况下,保持长宽比,并缩放源以适应目标。
此函数可用于将视图的内容捕获到绘图设备上,例如 QImage(例如,截取屏幕截图)或打印到 QPrinter。 例如:
{
 QGraphicsScene scene;
 scene.addItem(...
 ...

 QGraphicsView view(&scene);
 view.show();
 ...

 QPrinter printer(QPrinter::HighResolution);
 printer.setPageSize(QPrinter::A4);
 QPainter painter(&printer);

 view.render(&painter);

 QRect viewport = view.viewport()->rect();
 view.render(&painter,
             QRectF(0, printer.height() / 2,
                    printer.width(), printer.height() / 2),
             viewport.adjusted(0, 0, 0, -viewport.height() / 2));
}
               
void resetCachedContent()
//重置所有缓存的内容。调用此函数将清除视图的缓存。
//如果当前缓存模式为 CacheNone,则此函数不执行任何操作。当 backgroundBrush 或 QGraphicsScene::backgroundBrush 属性更改时,会自动调用此函数。如果重新实现QGraphicsScene::drawBackground() 或 drawBackground() 来绘制自定义背景,并且需要触发完全重绘,则只需调用此函数。
               
void resetTransform()
//将视图转换重置为单位矩阵。
               
void rotate(qreal angle)
//顺时针旋转当前视图。
               
QRect rubberBandRect()
//如果当前正在使用橡皮筋进行项目选择,则此函数返回当前橡皮筋区域(在视口坐标中)。当用户不使用橡皮筋时,此函数返回(空值)QRectF()。此 QRect 的一部分可以超出视觉视口,它可以包含负值。
               
void scale(qreal sx, qreal sy)
//按 (sx, sy) 缩放当前视图。
               
void setTransform(const QTransform &matrix, bool combine = false)
//设置视图的转换矩阵。参数2见QPainter详解的第46个函数。
               
void shear(qreal sh, qreal sv)
//通过 (sh, sv) 剪切当前视图转换。剪切效果见QTransform的第22个函数。

void translate(qreal dx, qreal dy)
//将当前视图转换转换为 (dx, dy)。