图形视图框架(Graphics View Framework)提供了一个用于管理大量定制2D图形图元(Item)并与之交互的表面(surface)。以及一个可用于可视化这些图元的视图(View)部件,它支持缩放和旋转。
该框架包含一个事件传播体系结构,该体系结构允许对场景(Scene)中的图元进行精确的交互。在其中的图元可以处理按键事件,鼠标按下,移动,释放和双击事件,它们也可以跟踪鼠标的移动。框架使用了BSP(Binary Space Partitioning)树来提供图元快速发现功能,因此它可以对大型场景进行可视化。
图形视图架构
图形视图提供了一种基于图元的模型视图处理的方法,类似于Model-View架构中的类QTableView,QTreeView和QListView,多个视图可以观察单个场景,并且场景包含各种几何形状的图元。
场景(Scene)
QGraphicsScene提供了“图形视图”的场景。该场景具有以下功能职责:
- 提供用于管理大量图元的快速界面;
- 将事件传播到每个图元;
- 管理图元状态,例如选择和焦点处理;
- 提供为进行转换的渲染功能,主要用于打印输出。
QGraphicesScene用作QGraphicsItem图元的容器,通过调用QGraphicsScene.addItem()可以将图元添加到场景中,然后通过调用各种图元发现函数来检索图元。QGraphicsScene.items()返回由点,矩形,多边形或者矢量路径所包含或与之相交的所有图元。QGraphicsScene.itemAt()返回特定点上的顶层图元。所有图元发现函数都以降序堆叠的方式返回图元(即,第一个返回的图元是最顶层的,最后一个图元是最底部的)。
scene =QGraphicsScene()
rect=scene.addRect(QRectF(0,0,100,100)) # 添加一个QGraphicsRectItem
item=scene.itemAt(50, 50, QTransform()) # 返回添加的item
QGraphicsScene的事件传播体系结构调度场景事件以传递给图元,并管理图元事件在图元之间的传播。如果场景在某个位置收到鼠标按下事件,那么场景会将事件传递到该位置上的所有图元。
QGraphicsScene也管理某些图元状态,例如图元选择和焦点。可以通过调用QGraphicsScene.setSelectionArea()设置任意形状的选择区间来选择场景中的图元。调用QGraphicsScene.selectedItems()可以获得所有当前选定图元的列表。QGraphicsScene处理的另一个状态是是否具有键盘焦点,可以通过调用QGraphicsScene.setFocusItem()或QGraphicsScene.setFocus()来设置图元的焦点,通过调用QGraphicsScene.focusItem()来获得当前的焦点图元。
调用QGraphicsScene.scene()将场景的一部分渲染到绘制设备中。
视图(View)
QGraphicsView提供视图部件,它可以将场景的内容可视化。视图窗口部件是一个可滚动区域,它提供了用于在大型场景中导航的滚动条。如果要启用OpenGL支持,可以通过调用QGraphicsView.setViewport()将QOpenGLWidget对象设置为视口。
scene =QGraphicsScene()
myPopulateScene(scene)
view = QGraphicsView(scene)
view.show()
视图从键盘和鼠标接收输入事件,然后将其转换为场景事件(在适当的情况下将其转换为场景坐标),然后再将事件发送到可视化场景。
使用转换矩阵QGraphicsView.transform(),视图可以转换场景的坐标,这样可以实现缩放和旋转等功能。QGraphicsView还提供了用于视图和场景坐标之间进行转换的函数:QGraphicsView.mapToScene()和QGraphicsView.mapFromScene()。
图片来源(doc.qt.io)
图元(Item)
QGraphicsItem是场景中图形图元的基类。在Qt的图形视图框架中提供了几种典型形状的标准图像图元,例如矩形(QGraphicsRectItem),椭圆(QGraphicsEllipseItem)和文本条目(QGraphicsTextItem)。QGraphicsItem支持以下功能:
- 鼠标按下,移动,释放和双击事件,以及鼠标悬停事件,滚轮事件和上下文菜单事件;
- 键盘输入焦点和按键事件;
- 拖放;
- 通过父子关系以及QGraphicsItemGroup进行分组;
- 碰撞检测。
图元位于局部坐标系统中,像QGraphicsView一样,它提供了许多用于在图元与场景之间以及条目与图元之间映射坐标的功能。另外,它可以使用矩阵变换QGraphicsItem.transform()函数变换其坐标系,这一点对旋转和缩放单个图元时相当有用。
图元可以包含其他图元(子图元)。父图元的转换由其所有子图元继承。但是,不管图元的累积转换如何,它的所有功能(例如, QGraphicsItem.contains(), QGraphicsItem.boundingRect(), QGraphicsItem.collidesWith())仍在局部坐标下运行。
QGraphicsItem支持通过QGraphicsItem.shape()函数和QGraphicsItem.collidesWith()这两个函数进行冲突检测。通过从QGraphicsItem.shape()返回项目的形状作为局部坐标QPainterPath,QGraphicsItem将处理所有碰撞检测。可以重新实现QGraphicsItem.collidesWith()来提供自己的冲突检测。
图片来源(doc.qt.io)
样例代码
使用QGraphicsScene创建一个场景,使用addLine()添加一条线,addTex()添加文本,addRect()添加一个矩形,addEllipse()添加一个圆。使用QGraphicsRectItem创建一个矩形图元,并将矩形图元的边框颜色设置为红色,使用setItem()将其添加到场景中。然后使用QGraphicsView创建一个视图,并将场景显示出来。完整代码如下:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPen,QColor
from PyQt5.QtWidgets import (QApplication, QGraphicsScene, QGraphicsView, QGraphicsRectItem)
if __name__ == '__main__':
app = QApplication(sys.argv)
scene = QGraphicsScene()
scene.addLine(20, 20, 200, 200)
scene.addText('Hello Graphics View')
scene.addRect(0, 0, 320, 240)
scene.addEllipse(100, 100, 100, 100)
rect = QGraphicsRectItem(99, 99, 102, 102)
rect.setPen(QPen(Qt.red))
scene.addItem(rect)
view = QGraphicsView(scene)
view.setWindowTitle('实战PyQt5: 图形视图 演示!')
view.resize(480, 320)
view.show()
sys.exit(app.exec())
运行结果如下图:
Graphics View 简单示例
本文知识点
- 图形视图框架的基本构成;
- 场景类QGraphicesScene;
- 视图类QGraphicsView;
- 图元类QGraphicsItem。
前一篇: 实战PyQt5: 081-文本浏览器QTextBrowser