1. Qt Graphics View框架概述
第一次接触Qt Graphics View框架时,我被它强大的2D图形处理能力震撼到了。这个框架就像是一个虚拟的画室,QGraphicsScene是画布,QGraphicsView是画框,而QGraphicsItem就是画布上的各种图形元素。在实际项目中,我用它开发过工业控制系统的HMI界面、数据可视化看板,甚至是简单的2D游戏引擎。
Graphics View框架最大的特点就是采用了三层结构:场景(Scene)、视图(View)和图元(Item)。这种设计让开发者可以轻松处理大量图形对象,支持复杂的交互操作。我记得刚开始使用时,最困惑的就是这三个层级之间的坐标转换问题。比如鼠标点击视图时,如何准确找到对应的图元?图元移动时,如何同步更新在不同视图中的显示?这些都需要理解框架的坐标系统。
2. 三大坐标系详解
2.1 场景坐标系
场景坐标系是Graphics View框架中最基础的坐标系,可以把它想象成一个无限延伸的虚拟画布。在我的一个数据可视化项目中,场景坐标系的原点(0,0)默认位于场景中心,x轴向右为正方向,y轴向下为正方向——这与常见的数学坐标系y轴方向相反,需要特别注意。
创建场景时,我们通常会设置一个初始的矩形区域:
QGraphicsScene *scene = new QGraphicsScene(-400, -300, 800, 600);
这行代码创建的场景左上角坐标是(-400,-300),宽度800,高度600。实际开发中我发现,如果不设置sceneRect,场景会根据添加的图元自动调整范围,但在复杂场景中显式设置会更可控。
2.2 视图坐标系
视图坐标系就是QGraphicsView窗口部件的物理坐标系,单位是像素。它的原点(0,0)在视图的左上角,x向右、y向下为正方向。所有鼠标事件最初都是用视图坐标传递的。
我在开发一个流程图工具时,经常需要处理视图和场景之间的坐标转换。比如要实现双击视图空白处创建新节点的功能,就需要把鼠标点击的视图坐标转换为场景坐标:
void MyView::mouseDoubleClickEvent(QMouseEvent *event) {
QPointF scenePos = mapToScene(event->pos());
// 在scenePos位置创建新节点
}
2.3 图元坐标系
每个图元(QGraphicsItem)都有自己的局部坐标系,原点通常在图元的中心点。这个坐标系会随着图元的旋转、缩放而变换。在图元的paint()函数中绘制的所有图形,都是基于这个局部坐标系。
我曾经实现过一个可旋转的仪表盘控件,深刻体会到图元坐标系的重要性。旋转图元时,所有的绘制操作都不需要改变,因为旋转是作用在整个图元坐标系上的:
void DialItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
painter->drawEllipse(-radius, -radius, 2*radius, 2*radius); // 始终以图元中心为原点
painter->drawLine(0, 0, 0, -radius); // 指针
}
3. 坐标系转换实战
3.1 视图与场景坐标互转
在实际开发中,视图和场景之间的坐标转换是最常用的功能。QGraphicsView提供了两个核心方法:
- mapToScene():将视图坐标转换为场景坐标
- mapFromScene():将场景坐标转换为视图坐标
我在一个地图应用中,需要实现点


2万+

被折叠的 条评论
为什么被折叠?



