QGraphicsView缩放适配窗口后绘制多边形坐标获取异常问题
问题相关基础实现
- 持有的代码文件:
mainwindow.cpp、mainwindow.h、包含QGraphicsView组件的UI界面文件 - 图像加载流程:将
QImage类型图像加载至QGraphicsPixmapItem实例,将命名为item的pixmap图元添加到场景scene中,通过ui->graphicsView->setScene(scene);完成视图与场景的绑定 - 已实现的缩放类功能按钮对应槽函数代码:
void MainWindow::on_actionZoom_In_triggered() { ui->graphicsView->scale(1.25,1.25); //item->update(1.25,1.25,1.25,1.25); //scene->update(1.25,1.25,1.25,1.25); } void MainWindow::on_actionZoom_Out_triggered() { ui->graphicsView->scale(0.75,0.75); //item->update(0.75,0.75,0.75,07.5); //scene->update(0.75,0.75,0.75,07.5); } void MainWindow::on_actionFit_Window_triggered() { ui->graphicsView->fitInView(scene->sceneRect(), Qt::KeepAspectRatio); }
异常表现
- 当前坐标获取逻辑:使用
QPointF point = ui->graphicsView->mapFromParent(event->pos());获取点位坐标 - 问题现象:上述坐标获取方式仅在图像未执行放大、缩小、适配窗口操作时可正常生效;执行缩放/适配操作后坐标取值错误,仅初始加载对应的视图区域可获取正确坐标
- 初步判断:坐标始终取自图像初始加载时的状态,
graphicsView执行缩放操作时图元item会同步缩放,但场景scene似乎未同步完成坐标变换 - 预想的两个解决方向:
- 直接调用
QGraphicsView的mousePressEvent方法 - 扩大坐标采集的有效响应区域
- 直接调用
复现步骤
- 加载图像
- 图像未做任何变换时绘制多边形,功能运行正常
- 执行缩放/适配操作后坐标取值错误,仅初始加载对应的视图区域可获取正确坐标
问题原因与修复方案
核心错误是坐标映射逻辑不完整:mapFromParent仅能将父窗口坐标系的点转换为graphicsView控件自身坐标系的点,完全没有处理视图缩放、适配带来的坐标系变换,因此视图变换后拿到的坐标和场景实际位置不匹配。
另外代码里注释的item->update()、scene->update()调用属于API误用:update()函数的作用是触发指定矩形区域的重绘,参数是需要刷新的矩形边界,不是缩放系数,不需要在缩放操作后手动调用这两个方法,QGraphicsView执行scale()、fitInView()后会自动维护变换矩阵、触发必要的重绘。
正确坐标获取方式
如果需要获取用于绘制多边形、和场景图元交互的场景坐标系坐标,在拿到视图控件坐标后,必须调用mapToScene完成视图到场景的坐标转换,该方法会自动适配所有缩放、平移、适配窗口产生的变换:
// 1. 先将父窗口传递的鼠标坐标转换为graphicsView视口坐标 QPoint viewPos = ui->graphicsView->mapFromParent(event->pos()); // 2. 核心:将视口坐标映射为场景坐标,自动适配所有视图变换 QPointF scenePos = ui->graphicsView->mapToScene(viewPos);
如果需要获取和图像像素对齐的图元本地坐标,可以再加一层场景到图元的映射:
QPointF itemPos = item->mapFromScene(scenePos);
对预想方案的说明
- 调用
QGraphicsView的mousePressEvent本身不能直接解决问题,只要在鼠标事件处理逻辑中使用上述mapToScene的坐标映射逻辑,不管是重写主窗口事件、给view装事件过滤器还是自定义view类重写鼠标事件,都能拿到正确坐标 - 扩大坐标采集有效响应区域属于治标不治本的方案,本质是坐标系映射逻辑错误,调整响应范围无法解决变换带来的坐标偏移问题。
内容的提问来源于stack exchange,提问作者Mgdej
相关产品推荐
相关产品推荐

