Qt/C++面试【速通笔记九】—视图框架机制
在Qt中,QGraphicsView
和QGraphicsScene
是用于构建二维图形界面的核心组件。它们的设计使得开发者能够高效地管理和渲染图形项,支持丰富的用户交互,例如缩放、旋转、平移等。
1. QGraphicsScene和QGraphicsView的基本概念
QGraphicsScene
QGraphicsScene
是Qt中的图形场景类,它负责管理所有的图形项(即QGraphicsItem
)。场景本身定义了一个坐标系统(场景坐标),用于描述所有图形项的位置、大小、状态等。可以理解为图形项的容器,所有图形项都可以添加到场景中。
QGraphicsView
QGraphicsView
是一个视图窗口,它通过渲染QGraphicsScene
中的图形项将场景的内容显示到屏幕上。它提供了缩放、旋转、平移等功能,能够让用户与图形项进行交互。QGraphicsView
将场景坐标转换为视图坐标,从而影响图形项在屏幕上的显示位置。
2. QGraphicsView框架的主要组件
- QGraphicsScene:用于管理和存储图形项(如矩形、线条、图片等)。
- QGraphicsItem:图形项,是场景中的具体内容,可以是任何可视化元素,如矩形、圆形、图片等。
- QGraphicsView:用于显示
QGraphicsScene
,并为用户提供交互功能。
3. 坐标系统与坐标转换
在QGraphicsView
框架中,有三个常见的坐标系统:
- 场景坐标(Scene Coordinates):这是场景中的全局坐标系统,所有图形项的位置和大小都通过场景坐标来定义。
- 视图坐标(View Coordinates):这是视图窗口的局部坐标系统,表示图形项在屏幕上的显示位置。由于视图支持缩放、平移等操作,视图坐标会随着这些变换而变化。
- 项坐标(Item Coordinates):这是图形项内部的局部坐标系统,描述图形项内部元素的位置。例如,矩形项的左上角坐标。
坐标转换
Qt提供了几种方法来进行坐标系统之间的转换。通过这些转换,您可以方便地在不同坐标系统之间进行转换,确保图形项、场景和视图的协调。
从场景坐标到视图坐标
假设您有一个场景坐标scenePoint
,可以使用QGraphicsView::mapFromScene()
方法将其转换为视图坐标:
QPointF scenePoint(50, 50); // 场景中的点
QPointF viewPoint = view.mapFromScene(scenePoint); // 转换为视图坐标
从视图坐标到场景坐标
如果您有一个视图坐标viewPoint
,可以使用QGraphicsView::mapToScene()
方法将其转换为场景坐标:
QPointF viewPoint(200, 150); // 视图中的点
QPointF scenePoint = view.mapToScene(viewPoint); // 转换为场景坐标
从项坐标到场景坐标
对于图形项,假设您有一个局部坐标localPoint
,可以使用QGraphicsItem::mapToScene()
方法将其转换为场景坐标:
QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 100, 100);
QPointF localPoint(20, 20); // 项坐标
QPointF scenePoint = rectItem->mapToScene(localPoint); // 转换为场景坐标
从场景坐标到项坐标
如果您有场景坐标scenePoint
,并且希望知道它相对于某个图形项的位置,可以使用QGraphicsItem::mapFromScene()
方法:
QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 100, 100);
QPointF scenePoint(50, 50); // 场景坐标
QPointF localPoint = rectItem->mapFromScene(scenePoint); // 转换为项坐标
4. QGraphicsView的交互功能
QGraphicsView
不仅用于显示场景,还提供了多种交互功能,例如缩放、平移、旋转等。这些功能可以大大增强用户体验,让应用程序更具交互性。
视图缩放
通过鼠标滚轮事件或者键盘快捷键,您可以实现视图的缩放。例如,可以使用scale()
方法来缩放视图:
view.scale(1.2, 1.2); // 放大视图
view.scale(0.8, 0.8); // 缩小视图
视图平移
可以使用translate()
方法平移视图的内容:
view.translate(50, 50); // 将视图内容平移50个像素
视图旋转
QGraphicsView
还支持视图的旋转操作:
view.rotate(45); // 旋转视图45度
5. 完整示例:QGraphicsView的使用
下面是一个完整的Qt示例,展示了如何创建一个QGraphicsScene
和QGraphicsView
,并实现一些基本功能,如坐标转换、鼠标点击事件、缩放等:
#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() | 将视图中的点转换为场景中的坐标 |