Qt/C++面试【速通笔记九】—视图框架机制

在Qt中,QGraphicsViewQGraphicsScene是用于构建二维图形界面的核心组件。它们的设计使得开发者能够高效地管理和渲染图形项,支持丰富的用户交互,例如缩放、旋转、平移等。


1. QGraphicsScene和QGraphicsView的基本概念

QGraphicsScene

QGraphicsScene 是Qt中的图形场景类,它负责管理所有的图形项(即QGraphicsItem)。场景本身定义了一个坐标系统(场景坐标),用于描述所有图形项的位置、大小、状态等。可以理解为图形项的容器,所有图形项都可以添加到场景中。

QGraphicsView

QGraphicsView 是一个视图窗口,它通过渲染QGraphicsScene中的图形项将场景的内容显示到屏幕上。它提供了缩放、旋转、平移等功能,能够让用户与图形项进行交互。QGraphicsView将场景坐标转换为视图坐标,从而影响图形项在屏幕上的显示位置。


2. QGraphicsView框架的主要组件

  • QGraphicsScene:用于管理和存储图形项(如矩形、线条、图片等)。
  • QGraphicsItem:图形项,是场景中的具体内容,可以是任何可视化元素,如矩形、圆形、图片等。
  • QGraphicsView :用于显示QGraphicsScene,并为用户提供交互功能。

3. 坐标系统与坐标转换

QGraphicsView框架中,有三个常见的坐标系统:

  1. 场景坐标(Scene Coordinates):这是场景中的全局坐标系统,所有图形项的位置和大小都通过场景坐标来定义。
  2. 视图坐标(View Coordinates):这是视图窗口的局部坐标系统,表示图形项在屏幕上的显示位置。由于视图支持缩放、平移等操作,视图坐标会随着这些变换而变化。
  3. 项坐标(Item Coordinates):这是图形项内部的局部坐标系统,描述图形项内部元素的位置。例如,矩形项的左上角坐标。
坐标转换

Qt提供了几种方法来进行坐标系统之间的转换。通过这些转换,您可以方便地在不同坐标系统之间进行转换,确保图形项、场景和视图的协调。

从场景坐标到视图坐标

假设您有一个场景坐标scenePoint,可以使用QGraphicsView::mapFromScene()方法将其转换为视图坐标:

cpp 复制代码
QPointF scenePoint(50, 50);  // 场景中的点
QPointF viewPoint = view.mapFromScene(scenePoint);  // 转换为视图坐标
从视图坐标到场景坐标

如果您有一个视图坐标viewPoint,可以使用QGraphicsView::mapToScene()方法将其转换为场景坐标:

cpp 复制代码
QPointF viewPoint(200, 150);  // 视图中的点
QPointF scenePoint = view.mapToScene(viewPoint);  // 转换为场景坐标
从项坐标到场景坐标

对于图形项,假设您有一个局部坐标localPoint,可以使用QGraphicsItem::mapToScene()方法将其转换为场景坐标:

cpp 复制代码
QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 100, 100);
QPointF localPoint(20, 20);  // 项坐标
QPointF scenePoint = rectItem->mapToScene(localPoint);  // 转换为场景坐标
从场景坐标到项坐标

如果您有场景坐标scenePoint,并且希望知道它相对于某个图形项的位置,可以使用QGraphicsItem::mapFromScene()方法:

cpp 复制代码
QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 100, 100);
QPointF scenePoint(50, 50);  // 场景坐标
QPointF localPoint = rectItem->mapFromScene(scenePoint);  // 转换为项坐标

4. QGraphicsView的交互功能

QGraphicsView不仅用于显示场景,还提供了多种交互功能,例如缩放、平移、旋转等。这些功能可以大大增强用户体验,让应用程序更具交互性。

视图缩放

通过鼠标滚轮事件或者键盘快捷键,您可以实现视图的缩放。例如,可以使用scale()方法来缩放视图:

cpp 复制代码
view.scale(1.2, 1.2);  // 放大视图
view.scale(0.8, 0.8);  // 缩小视图
视图平移

可以使用translate()方法平移视图的内容:

cpp 复制代码
view.translate(50, 50);  // 将视图内容平移50个像素
视图旋转

QGraphicsView还支持视图的旋转操作:

cpp 复制代码
view.rotate(45);  // 旋转视图45度

5. 完整示例:QGraphicsView的使用

下面是一个完整的Qt示例,展示了如何创建一个QGraphicsSceneQGraphicsView,并实现一些基本功能,如坐标转换、鼠标点击事件、缩放等:

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

class MyView : public QGraphicsView {
public:
    MyView(QGraphicsScene *scene) : QGraphicsView(scene) {
        setRenderHint(QPainter::Antialiasing);
        setRenderHint(QPainter::SmoothPixmapTransform);
    }

protected:
    void mousePressEvent(QMouseEvent *event) override {
        QPointF viewPoint = event->pos();  // 获取视图坐标
        QPointF scenePoint = mapToScene(viewPoint);  // 转换为场景坐标
        qDebug() << "Mouse clicked at view point:" << viewPoint << ", scene point:" << scenePoint;
    }

    void wheelEvent(QWheelEvent *event) override {
        if (event->angleDelta().y() > 0) {
            scale(1.2, 1.2);  // 放大
        } else {
            scale(0.8, 0.8);  // 缩小
        }
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QGraphicsScene scene;
    QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 100, 100);
    rectItem->setBrush(Qt::blue);  // 设置矩形颜色为蓝色
    scene.addItem(rectItem);

    MyView view(&scene);  // 使用自定义视图类
    view.show();

    return app.exec();
}

6. QGraphicsView常用函数一览

在使用QGraphicsView时,您将会用到一些常见的函数。下面是一些QGraphicsView类的主要函数及其功能:

分组 函数 功能描述
场景 void setScene() 设置关联显示的场景
void setSceneRect() 设置场景在视图中可见的部分的矩形区域
void setAlignment() 设置场景在视图中的对齐方式,缺省是上左对齐
外观 void setBackgroundBrush() 设置场景的背景画刷
void setForegroundBrush() 设置场景的前景画刷
void setRenderHints() 设置视图的绘制选项
交互 void setInteractive() 是否允许场景可交互,如果禁用交互,则任何键盘盘或鼠标操作都被忽略
QRect rubberBandRect() 返回选择矩形框区域
void setRubberBandSelectionMode() 选择模式,参数为枚举类型Qt::ItemSelectionMode
坐标 QPoint mapFromScene() 将场景中的点转换为视图中的坐标
QPointF mapToScene() 将视图中的点转换为场景中的坐标

相关推荐
野生风长4 小时前
C++入门基础:从命名空间到引用与指针的全面解析
开发语言·c++
疯狂打码的少年5 小时前
【软件工程】软件质量保证(ISO/IEC 9126质量特性)
笔记
Escalating_xu5 小时前
C++可变参数模板与引用折叠精讲
开发语言·c++
云泽8086 小时前
Visual Studio 2026 新手保姆级教程:环境搭建、界面优化与编译器配置详解
开发语言·c++·c·开发工具·visual studio
fqbqrr7 小时前
2607d,C++细节比不上d
c++·d
^yi7 小时前
【C++】继承的那些事儿~
c++·继承·菱形继承·隐藏·final·继承原理·多继承的指针偏移
龙仔7258 小时前
SQL Server OS_Core 数据库全自动备份【完整笔记·可直接复用】
数据库·笔记·oracle
ShineWinsu8 小时前
对于Linux:模版方法类的解析以及socket、TcpSocket的封装
linux·c++·面试·socket·模板方法模式·封装·tcpsocket
殷忆枫9 小时前
AI笔记三十七:AI边缘端道桥安全监测系统:YOLOv8n推理与Web监控全解析
笔记·yolo
hold?fish:palm9 小时前
9 找到字符串中所有字母异位词
c++·算法·leetcode