Qt的图形/视图架构(Graphics/View Framework)是一个用于管理和交互大量2D图形项的系统,它提供了一种高效的方式来处理复杂的自定义图形场景。这个架构主要由三个核心类组成:QGraphicsScene
、QGraphicsView
和QGraphicsItem
。
架构组成
1. QGraphicsScene (场景)
- 作用:作为所有图形项的容器,管理着大量的
QGraphicsItem
对象 - 功能:
- 提供场景坐标系系统
- 管理图形项的生命周期
- 处理图形项之间的碰撞检测
- 支持场景事件传播
- 提供场景渲染的接口
2. QGraphicsView (视图)
- 作用:作为场景的可视化窗口,可以有一个或多个视图观察同一个场景
- 功能:
- 提供滚动条支持
- 支持缩放和旋转
- 处理视图变换
- 管理视口(viewport)渲染
- 支持OpenGL加速
3. QGraphicsItem (图形项)
- 作用:场景中的基本图形元素基类
- 功能:
- 定义图形项的几何形状
- 处理鼠标和键盘事件
- 支持拖放操作
- 提供碰撞检测
- 支持分组和父子关系
架构优势
- 高效渲染:采用BSP树(Binary Space Partitioning)优化图形项查找
- 灵活的坐标系统:
- 场景坐标(Scene Coordinates)
- 视图坐标(View Coordinates)
- 图形项局部坐标(Item Coordinates)
- 强大的交互能力:内置支持鼠标/键盘事件、拖放、动画等
- 内存管理:场景负责管理所有图形项的生命周期
- 多视图支持:一个场景可以有多个视图以不同方式查看
用虚拟的画室来比喻
-
QGraphicsScene(场景) - 相当于"画室的地板"
- 就像一个大画布,所有图形都放在这上面
- 负责记住每个图形的位置、大小等信息
- 可以同时管理成千上万个图形元素
-
QGraphicsView(视图) - 相当于"观察画室的窗户"
- 你可以有多个"窗户"观察同一个画室
- 可以放大缩小(就像用放大镜看)
- 可以移动查看不同区域(像滑动手机屏幕)
-
QGraphicsItem(图形项) - 相当于"画室里的各种图形"
- 比如圆形、方形、文字等
- 每个图形都可以单独移动、旋转、缩放
- 可以设置是否允许被鼠标拖动或选中
工作流程举例
想象你在做一个简单的绘图程序:
- 先准备一个空画室(创建Scene)
- 在画室里放几个图形:一个红圆圈、一个蓝方块(创建Item并添加到Scene)
- 开个窗户让大家能看见画室里的内容(创建View显示Scene)
- 用户可以通过窗户:
- 用鼠标拖动图形移动位置
- 滚轮放大缩小看细节
- 选中某个图形修改颜色
基本使用示例
// 创建场景
QGraphicsScene *scene = new QGraphicsScene();
scene->setSceneRect(0, 0, 800, 600); // 设置场景大小
// 创建视图并关联场景
QGraphicsView *view = new QGraphicsView(scene);
view->setRenderHint(QPainter::Antialiasing); // 抗锯齿
view->setWindowTitle("Graphics View示例");
view->resize(800, 600);
// 添加图形项到场景
QGraphicsRectItem *rect = scene->addRect(50, 50, 200, 100);
rect->setBrush(Qt::blue);
rect->setFlag(QGraphicsItem::ItemIsMovable); // 允许移动
QGraphicsEllipseItem *ellipse = scene->addEllipse(300, 100, 150, 150);
ellipse->setBrush(Qt::red);
ellipse->setFlag(QGraphicsItem::ItemIsSelectable); // 允许选择
// 显示视图
view->show();
高级特性
1. 自定义图形项
通过继承QGraphicsItem
可以创建自定义图形项:
class CustomItem : public QGraphicsItem {
public:
QRectF boundingRect() const override {
return QRectF(-50, -50, 100, 100);
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override {
painter->setBrush(Qt::green);
painter->drawEllipse(-50, -50, 100, 100);
painter->drawText(-20, 0, "Custom");
}
};
// 使用自定义项
CustomItem *custom = new CustomItem();
scene->addItem(custom);
2. 动画支持
Qt提供了QGraphicsItemAnimation
和QTimeLine
来实现动画效果:
QGraphicsRectItem *animatedRect = scene->addRect(0, 0, 50, 50);
animatedRect->setBrush(Qt::yellow);
QGraphicsItemAnimation *animation = new QGraphicsItemAnimation;
animation->setItem(animatedRect);
QTimeLine *timer = new QTimeLine(2000); // 2秒动画
timer->setFrameRange(0, 100);
animation->setTimeLine(timer);
// 设置动画路径
for(int i = 0; i < 200; ++i) {
animation->setPosAt(i/200.0, QPointF(i, i));
}
timer->start();
3. 碰撞检测
场景内置了碰撞检测功能:
// 检查某个项是否与其他项碰撞
QList<QGraphicsItem*> collidingItems = item->collidingItems();
// 自定义碰撞检测
bool MyItem::collidesWithItem(const QGraphicsItem *other, Qt::ItemSelectionMode mode) const {
// 自定义碰撞逻辑
return this->shape().intersects(other->shape());
}
性能优化技巧
-
使用BSP树:对于静态场景,可以启用BSP树索引
scene->setItemIndexMethod(QGraphicsScene::BspTreeIndex);
-
批量渲染:对于大量相似项,考虑使用
QGraphicsItemGroup
-
部分更新:只更新需要重绘的区域
view->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
-
OpenGL加速:对于复杂场景,使用OpenGL渲染
view->setViewport(new QOpenGLWidget);
-
项缓存:对复杂项启用缓存
item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
实际应用场景
- 绘图软件:如简易版的Photoshop
- CAD/CAM系统:工程制图应用
- 数据可视化:图表、网络拓扑图等
- 游戏开发:2D游戏引擎
- 交互式教学工具:物理/数学模拟
Qt图形/视图架构提供了强大的2D图形处理能力,通过合理的场景管理和视图控制,可以轻松构建复杂的图形应用程序。