logo资料库

Qt的graphics View框架(中文).doc

第1页 / 共6页
第2页 / 共6页
第3页 / 共6页
第4页 / 共6页
第5页 / 共6页
第6页 / 共6页
资料共6页,全文预览结束
Qt 的 graphics View 框架(转载) Graphics View 提供了一个界面,它既可以管理大数量的定制 2D graphical items,又可与它们交互,有一个 view widget 可以把这些项绘制出来,并支持 旋转与缩放。这个柜架也包含一个事件传播结构,对于在 scene 中的这些 items, 它具有双精度的交互能力。Items 能处理键盘事件,鼠标的按,移动、释放、双 击事件,也可以跟踪鼠标移动。Graphics View 使用 BSP 树来提供对 item 的快 速查找,使用这种技术,它可以实时地绘制大规模场景,甚至以百万 items 计。 Graphics View 在 Qt 4.2 中被引用,它替代了它的前辈 QCanvas。 Graphics View的体系结构 Graphics View 提供的是一种类似于 Qt model-view 的编程。多个 views 可以监 视同一个场景,而场景包含多个具有多种几何外形的 items。 场景 QGraphicsScene 表示 Graphics View 中的场景,它有以下职责: 为管理大量的 items 提供一个快速的接口。 传播事件到每个 item。 管理 item 的状态,例如选择,焦点处理。 提供未经变换的渲染功能,主要用于打印。 场景作为 QGraphicsItem 对象的容器。通过调用 QgraphicsScene::addItem()把 这些 Items 加入到场景中。可以使用众多的查找函数来获取特定的 items。 QGraphicsScene:items()与它的许多重载函数可获取那些与点、矩形,多边形, 向量路径等相交或是有包含有关系的 items。QGraphicsScene::itemAt()返回特 定上最顶端的 item。所有的 item 查找函数都以出栈序列返回(也就是说,第一 个返回的是最顶端的,最后一个返回的是最底端的)。 QGraphicsScene QGraphicsRectItem QGraphicsItem //item==rect; QGraphicsScene 的事件传播结构会把场景事件投递到 items,也管理多个 items 之间的传递。假如场景收到了鼠标在某个位置 press 事件,场景会把这个事件投 递给处在那个位置的 item。QGraphicsScene 也管理某种 item 状态,像选择与焦 点。你可以通过调用 QGraphicsScene::setSelectionArea()来选择 items,它需 要提供一个任意的形状为参数。这个函数也作为在 QGraphicsView 实现橡皮筋选 择功能的一个基础。为得到这些已经被选择的 items,调用 QGraphicsScene::selectedItem()。另一个状态处理是是否一个 item 拥有键盘 输入焦点。你可以调用 QGraphicsScene::setFocusItem()或 QGraphics::setFocus()来设定焦点,也可用 QGraphicsScene::focusItem()来 得到当前拥有焦点的那个 item。最后,QGraphicsScene 允许你通过调用 QGraphicsScene::render()函数把部分场景送到绘图设备进行渲染。 视图 *rect=scene.addRect(QRectF(0,0,100,100)); scene; *item=scene.itemAt(50,50);
QGraphicsView 提供了视图部件,它可视化场景中的内容。你可以联结多个视图 到同一个场景,对这个相同的数据集提供几个视口。视口部件是一个滚动区域, 它提供了滚动条以对大场景进行浏览。为了使用 OpenGL,你应该调用 QGraphicsView::setViewport()来把一个 QGLWidget 设为视口。视图从键盘,鼠 标接收输入事件,在发送这些事件到场景之前,会对这些事件进行适当的翻译(把 事件坐标转换成对应的场景坐标)。 利用转换矩阵,QGraphicsView::matrix(),视图可变换场景的坐标系统。这允许 高级的导航特性,如缩放,旋转。为了方便,QGraphicsView 也提供了在视图与 场景之间进行坐标转换的函数: QGraphicsView::mapToScene(),QGraphicsView::mapForScene()。 The Item QGraphicsItem 是场景中图形 items 的基类。Graphics View 提供了一些标准的、 用于典型形状的 items。像矩形(QGraphicsRectItem),椭圆 (QGraphicsEllipseItem),文本(QGraphicsTextItem),当你写定制的 item 时, 那些最有用的一些 QGraphicsItem 特性也是有效的。除此这外,QGraphicsItem 支持以下特性: *鼠标按、移动、释放、双击事件,鼠标悬停事件,滚轮事件,弹出菜单事件。 *键盘输入焦点,键盘事件。 *拖拽 *组,包括父子关系,使用 QGraphicsItemGroup *碰撞检测 Items 如同 QGraphicsView 一样,位于本地坐标系,它也为 item 与场景之间, item 与 item 之间的坐标转换提供许多工具函数。而且,也像 QGraphicsView 一 样,它使用矩阵来变换它的坐标系统:QGraphicsItem::matrix()。它对旋转与 缩放单个的 Item 比较有用。 Items 可以包含别的 items(孩子)。父 items 的转换被它的子孙所继承。然而, 它的所有函数(也就是, QGraphicsItem::contains(),QGraphicsItem::boundingRect(),QGraphicsItem: :collidesWith()),不会积累这些转换,依然在本地坐标下工作。 QGraphicsItem 通过 QGraphicsItem::shape(),QGraphicsItem::collideWith()) 来支持碰撞检测。这两个都是虚函数。从 shape()返回你的 item 的形状(以本 地坐标 QPainterPath 表示),QGraphicsItem 会为你处理所有的碰撞检测。假 如你想提供自己的碰撞检测,你应该重新实现 QGraphicsItem::collideWith()。
Graphics View 坐标系统 Graphics View 基于笛卡尔坐标系。item 在场景中的位置与几何形状通过 x,y 坐标表示。当使用未经变形的视图来观察场景时,场景中的一个单位等于屏幕上 的一个像素。在 Graphics View 中有三个有效的坐标系统:Item 坐标系,场景 坐标系,视图坐标系。为了简化你的实现,Graphics View 提供了方便的函数, 允许三个坐标系之间相互映射。 当渲染时,Graphics View 的场景坐标对应于 QPainter 的逻辑坐标,视图坐标 与设备坐标相同。 Item 坐标 Items 位于它们自己的坐标系中。它的坐标都以点(0,0)为中心点,这也是所有 变换的中心点。在 item 坐标系中的几何图元,经常被称为 item 点,item 线, item 矩形。当创建一个定制的 item,item 坐标是所需要考虑的。QGraphicsScene 与 QGraphicsView 可以为你执行所有转换,这使得实现定制的 item 变得容易。 举例来说,假如你收到鼠标按或是拖进入事件,事件的位置以 item 坐标的形式 给出。QGraphicsItem::contain()虚函数,当某个点的位置在你的 item 范围内 时,返回 true,否则返回 false。这个点参数使用 item 坐标,相似地,item 的 包围矩形与形状也使用 item 坐标。 Item 位置指的是 item 的中心点在它父亲的坐标系中的坐标。以这种思想来看, 场景指的就是那些祖先最少的 item 的“父亲”。最上级的 Item 位置就是在场景 中的位置。 子坐标与父坐标之间是相关的,假如孩子未经变换,子坐标与父坐标之间的差值 等于在父坐标系下,父 item 与子 item 之间的距离。例如,假如一个未经变换的 子 item 位置与其父 item 的中心重合,那么这两个 item 的坐标系统完全相同。 如果孩子的位置是(10,0),那么孩子坐标系中的(0,10)点,对应于父坐标系 中的(10,10)点。 因为 item 的位置与变换是相对于父 item 的,子 item 的坐标不会被父亲的变换 影响,尽管父 item 的变换隐含地对子 item 做了变换。在上面的例子中,即使父 item 旋转,缩放,子 item 的(0,10)点依然对应于父 item 的(10,10)点。然而, 相对于场景来讲,子 item 会遵循父 item 的变换。假如父 item 被缩放(2X,2X), 子 item 的位置在场景中的坐标是(20,0),它的(10,0)点则与场景中的(40, 0)对应 。除了 QGraphicsItem::pos(),QGraphicsItem 的函数以 Item 坐标工 作,如一个 item’s 包围矩形总是以 item 坐标的形式给出。
场景坐标 场景坐标系统描述了每个最顶级 item 的位置,也是从视图向场景投递场景事件 的基础。场景中的每个 item 有场景位置与包围矩形 (QGraphicsItem::scenePos(),QGraphicsItem::sceneBoundingRect()), 另 外,它有自己本地 item 位置与包围矩形。场景位置描述了 item 在场景坐标下的 位置,它的场景包围矩形则用于 QGraphicsScene 决定场景中哪块区域发生了变 化。场景中的变化通过 QGraphicsScene::changed()信号来通知,它的参数是场 景矩形列表。 视图坐标 视图坐标是 widget 的坐标,视图坐标中每个单位对应一个像素。这种坐标的特 殊之处在于它是相对于 widget 或是视口的,不会被所观察的场景所影响。 QGraphicsView 的视口的左上角总是(0,0),右下角总是(视口宽,视口高)。 所有的鼠标事件与拖拽事件,最初以视图坐标表示,就应该把这些坐标映射到场 景坐标以便与 item 交互。 坐标映射 经常,处理场景中 item 时,在场景与 item 之间,item 与 item 之间,视图与场 景之间进行坐标映射,形状映射是非常有用的。举例来讲,当你在 QGraphicsView 的视口中点击鼠标时,你应该通过调用 QGraphicsView::mapToScence()与 QGraphicsScene::itemAt()来获知光标下是场景中的哪个 item。假如你想获知 一个 item 位于视口中的什么位置,你应该先在 item 上调用 QGraphicsItem::mapToScene(),然后调用 QGraphicsView::mapFromScene()。最 后,假如你想在一个视图椭圆中有哪些 items,你应该把 QPainterPath 传递到 mapToScene(),然后再把映射后的路径传递到 QGraphicsScene::items()。 你可以调用 QGraphicsItem::mapToScene()与 QGraphicsItem::mapFromScene() 在 item 与场景之间进行坐标与形状的映射。也可以在 item 与其父 item 之间通 过 QGraphicsItem::mapToParent()与 QGraphicsItem::mapFromItem()进行映 射。所有映射函数可以包括点,矩形,多边形,路径。视图与场景之间的映射也 与此类似。对于从视图与 item 之间的映射,你应该首先映射到场景,然后再从 场景向 item 进行映射。 关键特性 缩放与旋转 QGraphicsView 通过 QGraphicsView::setMatrix()支持同 QPainter 一样的仿射 变换,通过对一个视图应用变换,你可以很容易地支持普通的导航特性如缩放与 旋转。下面是一个例子: class View:;public QGraphicsView { Q_OBJECT //….. public slots: void zoomIn() {scale(1.2,1.2);} void zoomOut() {scale(1/1.2,1/1.2);}
void rotateLeft() {rotate(-10);} void rotateRight() {rotate(10);} }; 这些槽应与 QToolButtons 联接,并使 autoRepeat 有效。当对视图变换时, QGraphicsView 会对视图中心进行校正。 拖拽 因为 QGraphicsView 继承自 QWidget,它也提供了像 QWidget 那样的拖拽功能, 另处,为了方便,Graphics View 柜架也为场景,每个 item 提供拖拽支持。当 视图接收到拖拽事件,它可翻译为 QGraphicsSceneDragDropEvent,再发送到场 景。场景接管这个事件,把它发送到光标下接受拖拽的第一个 item。 从一个 item 开始拖拽时,创建一个 QDrag 对象,传递开始拖拽的那个 widget 的指针。Items 可以同时被多个视图观察,但只有一个视图可以开始拖拽。拖拽 在多数情况下是从按下鼠标或是移动鼠标开始的,因此,在 mousePressEvent() 或 mouseMoveEvent()中,你可以从事件中得到那个原始的 widget 指针,例如: void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { QMimeData *data=new QMimeData; data->setColor(Qt::green); QDrag *drag=new QDrag(event->widget()); drag->setMimeData(data); drag->start(); } 为了在场景中载取拖拽事件,你应重新实现 QGraphicsScene::dragEnterEvent() 和在 QGraphicsItem 的子类里任何与你特定场景需要的事件处理器。items 也可 以通过调用 QGraphicsItem::setAcceptDrops()获得拖拽支持,为了处理将要进 行的拖拽,你需要重新实现 QGraphicsItem::dragEnterEvent(),QGraphicsItem::dragMoveEvent(),QGraph icsItem::dragLeaveEvent()和 QGraphicsItem::dropEvent()。 光标与工具提示 像 QWidget 一样,QGraphicsItem 也支持光标(QgraphicsItem::setCursor)与 工具提示(QGraphicsItem::setToolTip())。当光标进入到 item 的区域,光标与 工具提示被 QGraphicsView 激活(通过调用 QGraphicsItem::contains()检测)。 你也可以直接在视图上设置一个缺省光标(QGraphicsView::setCursor)。 动画 Graphics View 支持几种级别的动画。你可以很容易地通过把 QGraphicsItemAnimatoin 与你的 item 联结来 装配出动画路径,这允许以时间线来控制动画,在所有平台上以稳定的速率运作。 QGraphicsItemAnimation 允许你为 item 的位置,旋转,缩放,剪切,变换等产 生一条路径,动画可以用 QSlider 来控制,或更为普遍使用的 QTimeLine。 另一种是从 QObject 和 QGraphicsItem 继承,item 可以设置自己的定时器,以 在 QObject::timeEvent()中增加步进的方式来控制动画。 第三种,是通过调用 QGraphicsScene::advance()来推进场景,它又依次调用 QGraphicsItem::advance().
OpenGL 渲染 为了使用 OpenGL 渲染,你要设置一个新的 QGLWidget 作为 QGraphicsView 的视 口:QGraphicsView::setViewPort()。假如你让 OpenGL 提供反锯齿功能,你需 要 OpenGL 采样缓冲支持。 QGraphicsView view(&scene); view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); Item 组 通过把一个 item 做为另一个 item 的孩子,你可以得到 item 组的大多数本质特 性:这些 items 会一起移动,所有变换 会从父到子传递。QGraphicsItem 也可以为它的孩子处理所有的事件,这样就允 许以父亲代表它所有的孩子,可以有效地把所有的 items 看作一个整体。 另外,QGraphicsItemGroup 是一个特殊的 item,它既对孩子事件进行处理又有一 个接口把 items 从一个组中增加和删除。把一个 item 加到 QGraphicsItemGroup 仍会保留 item 的原始位置与变换,而给一个 item 重新指 定父 item 则会让 item 根据其新的父亲重新定位。可以用 QGraphicsScene::createItemGroup()建组。
分享到:
收藏