Qt Graphics View

Graphics View框架是用来处理大量2D图形对象的,适合需要高效管理和交互的场景,比如绘图软件、地图编辑或者游戏。它和QPainter的区别在于,Graphics View提供了更高级别的对象管理,而QPainter更偏向于直接绘制。

一、核心组件

  1. ‌**QGraphicsScene(场景)**‌

    • 作为图形项的容器,管理所有图元的存储、状态及事件传播‌。
    • 支持背景层、图形项层和前景层的分层绘制,可通过setBackgroundBrush()setForegroundBrush()设置背景/前景‌。
    • 提供碰撞检测、图元查询(如itemAt())及批量渲染(render())功能‌。
  2. ‌**QGraphicsView(视图)**‌

    • 用于显示场景内容,支持多视图查看同一场景,提供缩放、旋转、平移等交互操作‌。
    • 可通过继承并重写mouseMoveEvent()mousePressEvent()等实现自定义交互逻辑(如坐标追踪、点击响应)‌。
  3. ‌**QGraphicsItem(图元)**‌

    • 所有图形元素的基类,支持自定义形状、事件处理(如鼠标拖拽、键盘事件)及坐标变换‌14。
    • 典型应用包括可拖动的十字标记(CrossMarkItem)和可调整大小的兴趣区域(ROIRectItem)‌。

二、关键特性

  1. 事件处理

    • 图元可直接响应鼠标点击、悬停、拖拽及键盘事件,事件通过场景传播至目标图元‌。
      示例:
      通过重写hoverEnterEvent()hoverLeaveEvent()实现图元悬停缩放效果‌。
      重写 mousePressEvent(), keyPressEvent() 等实现交互。
    • 使用 QGraphicsSceneContextMenuEvent 处理右键菜单。
  2. 性能优化

    • 通过设置QGraphicsItem::ItemIgnoresTransformations避免不必要的变换计算‌。
  3. 坐标转换‌:

    • 场景坐标 ↔ 视图坐标:QGraphicsView::mapToScene()mapFromScene()
    • 项间坐标转换:QGraphicsItem::mapToItem()mapFromItem()
  4. 动画与效果‌:

    • 动画 ‌: 使用 QPropertyAnimationQGraphicsItemAnimation
    • 特效 ‌: 应用 QGraphicsEffect(如阴影、模糊)。
  5. 碰撞检测‌:

    • scene->collidingItems(item) 检测碰撞项。
    • QGraphicsItem::shape() 自定义碰撞形状。
  6. 性能优化‌:

    • 启用视图缓存:view.setCacheMode(QGraphicsView::CacheBackground)
    • 使用 QGraphicsItem::ItemIgnoresTransformations 避免项随视图缩放。

三、基本用法

复制代码
// 创建场景和项
QGraphicsScene scene;
QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 50);

// 创建视图并关联场景
QGraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing); // 抗锯齿
view.show();

四、开发建议

  • 模块化设计 ‌:将图元、视图逻辑分离,便于维护扩展(如独立实现CrossMarkItemGraphView类)‌。
  • 交互优化 ‌:使用QGraphicsView::setDragMode()启用拖拽模式,提升用户体验‌。
  • 内存管理‌: 项通常由场景负责删除,手动删除需谨慎。
  • 渲染性能 ‌: 避免过多复杂项;考虑使用 OpenGL 加速(QGraphicsView::setViewport(new QOpenGLWidget))。
  • 调试工具 ‌:利用QGraphicsScene::selectedItems()和焦点管理功能辅助调试复杂交互逻辑‌。

五、实例代码

1、基础实例:场景与视图初始化

复制代码
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    
    // 创建场景并设置范围
    QGraphicsScene *scene = new QGraphicsScene();
    scene->setSceneRect(0, 0, 800, 600);  // ‌:ml-citation{ref="1" data="citationList"}
    
    // 添加矩形图元
    QGraphicsRectItem *rectItem = new QGraphicsRectItem(100, 100, 200, 150);
    rectItem->setBrush(Qt::blue);
    scene->addItem(rectItem);  // ‌:ml-citation{ref="1,7" data="citationList"}
    
    // 创建视图并绑定场景
    QGraphicsView *view = new QGraphicsView(scene);
    view->setWindowTitle("Basic Example");
    view->show();
    
    return app.exec();
}

2、图元选择与坐标跟踪

实现功能‌:

  • 鼠标移动时实时显示场景坐标
  • 图元选中后支持键盘操作(删除、旋转、缩放)

关键代码‌:

复制代码
// 继承 QGraphicsView 实现自定义视图
class CustomView : public QGraphicsView {
protected:
    void mouseMoveEvent(QMouseEvent *event) override {
        QPoint viewPos = event->pos();
        QPointF scenePos = mapToScene(viewPos);
        emit positionChanged(scenePos);  // 发送坐标信号
    }
};

// 图元选中后处理键盘事件
void MyItem::keyPressEvent(QKeyEvent *event) {
    switch (event->key()) {
        case Qt::Key_Delete:
            scene()->removeItem(this);  // 删除图元 ‌
            break;
        case Qt::Key_Space:
            setRotation(rotation() + 90);  // 旋转 90°
            break;
    }
}

3、自定义图元实例

实现功能‌:

  • 十字标记支持鼠标拖拽
  • 拖拽时实时更新位置信号

‌关键代码:

复制代码
// CrossMarkItem.h
class CrossMarkItem : public QGraphicsItem {
public:
    QRectF boundingRect() const override {
        return QRectF(-size_/2, -size_/2, size_, size_);
    }
    
    void paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*) override {
        painter->drawLine(-size_/2, 0, size_/2, 0);  // 水平线
        painter->drawLine(0, -size_/2, 0, size_/2);   // 垂直线
    }
    
protected:
    QVariant itemChange(GraphicsItemChange change, const QVariant &value) override {
        if (change == ItemPositionChange) 
            emit positionChanged(value.toPointF());  // 发送位置变化信号
        return QGraphicsItem::itemChange(change, value);
    }
};

4、ROI 矩形与动态更新

实现功能‌:

  • 可调整大小的兴趣区域(ROI)
  • 实时显示 ROI 的坐标和尺寸

设计要点‌:

  • 继承 QGraphicsRectItem 并添加控制点
  • 在边缘点拖拽时更新 ROI 范围

‌关键代码:

复制代码
class ROIRectItem : public QGraphicsRectItem {
public:
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override {
        QPointF delta = event->pos() - event->lastPos();
        setRect(rect().adjusted(delta.x(), delta.y(), delta.x(), delta.y()));  // 动态调整矩形
    }
};
相关推荐
Wizard79723 分钟前
在linux 系统下的qt 安装mqtt库
linux·运维·qt
无名之逆25 分钟前
Hyperlane:Rust 生态中的轻量级高性能 HTTP 服务器库,助力现代 Web 开发
服务器·开发语言·前端·后端·http·面试·rust
江沉晚呤时27 分钟前
使用 .NET Core 实现 RabbitMQ 消息队列的详细教程
开发语言·后端·c#·.netcore
大模型铲屎官30 分钟前
从零精通机器学习:线性回归入门
开发语言·人工智能·python·算法·机器学习·回归·线性回归
搞不懂语言的程序员39 分钟前
单例模式详解(java)
java·开发语言·单例模式
WangMing_X1 小时前
C#实现图像缩放与裁剪工具
开发语言·c#·图像
Python破壁人手记1 小时前
《我的Python觉醒之路》之转型Python(十五)——控制流
java·服务器·开发语言·网络·python
yuyuyuliang001 小时前
Qt SQL-1
sql·qt
siy23331 小时前
[c语言日寄]浮点数的排序
c语言·开发语言·数据结构·笔记·学习
天人合一peng1 小时前
C# PaddleOCR字符识别
开发语言·c#