图形视图框架的坐标
创始人
2025-05-30 21:39:31

图形视图基于笛卡尔坐标系;项目在场景中的位置和几何图形由两组数字表示:X 坐标和 Y 坐标。使用未变换的视图观察场景时,场景上的一个单元由屏幕上的一个像素表示。

图形视图中有三种有效的坐标系:

  • 项目坐标
  • 场景坐标
  • 视图坐标

为了简化实现图形视图提供了三个坐标系之间进行映射。

项目的坐标:

项目位于其自己的局部坐标系中。它们的坐标通常以中心点 (0, 0) 为中心,这也是所有变换的中心。项目坐标系中的几何基元通常称为项目点、项目线或项目矩形。

创建自定义项目时,您只需担心项目坐标;QGraphicsScene 和 QGraphicsView 将为您执行所有转换。这使得实现自定义项变得非常容易。

项目位置是项目在其父坐标系中的中心点的坐标;有时称为坐标。从这个意义上说,这个场景被视为所有无父母项目的“父母”。顶级物品的位置位于场景坐标中。

子坐标相对于父坐标。如果子坐标未变换,则子坐标和父坐标之间的差异与父坐标中项目之间的距离相同。例如:如果未转换的子项精确定位在其父项的中心点,则这两个项的坐标系将相同。但是,如果子项的位置是 (10, 0),则子项的 (0, 10) 点将对应于其父项的 (10, 10) 点。

由于项的位置和转换相对于父项,因此子项的坐标不受父项转换的影响,尽管父项的转换隐式变换了子项。在上面的示例中,即使父级旋转和缩放,子项的 (0, 10) 点仍将对应于父项的 (10, 10) 点。然而,相对于场景,孩子将跟随父母的转变和位置。如果父项缩放 (2x, 2x),则子项的位置将位于场景坐标 (20, 0),其 (10, 0) 点将与场景中的点 (40, 0) 相对应。

场景坐标:

场景表示其所有项目的基本坐标系。场景坐标系描述每个顶级项目的位置,也构成了从视图传递到场景的所有场景事件的基础。

  • 项目可以使用 scenePos()来查看在场景的位置
  • 项目使用sceneBoundingPect()来查看场景的边界矩形
  • 场景中的变化使用QGraphicsScene::changed()信号进行通信

视图坐标:

视图的坐标是部件的坐标,视图坐标的每一个单位对应一个像素,原点为(0,0)总是在QGraphicsView视口的左上角,所有的鼠标事件和拖放事件最初都是使用视图视图坐标接收。

例子:

int main(int argc, char *argv[])
{QApplication a(argc, argv);QGraphicsScene scene(-200,-200,400,400);//创建一个场景QGraphicsRectItem item1(0,0,100,100);//创建一个圆item1.setPos(0,0);//设置位置scene.addItem(&item1);QGraphicsView view2;//创建第一个视图view2.setScene(&scene);//设置场景view2.resize(400,400);view2.show();//显示return a.exec();
}

 场景和视图的关系:

场景:

QGraphicsScene scene(-200,-200,400,400);//创建一个场景

这段代码代表的是该场景是从(-200,-200)到(400,400)的一个矩形

视图:

    QGraphicsView view2;//创建第一个视图view2.setScene(&scene);//设置场景view2.resize(400,400);//重置视图大小view2.show();//显示

场景和项目的关系:

  • 如果没设置位置的话,项目的(0.0)点会放置在场景的(0,0)点
  • 可以使用setPos()修改项目在视图中的位置

修改场景: 

例一:场景为QRectF(0,0,400,400),项目为(0,0,100,100)

    QGraphicsScene scene(0,0,400,400);//创建一个场景QGraphicsRectItem item1(0,0,100,100);//创建一个矩形scene.addItem(&item1);//视图部分省略

由于项目的起始点为(0,0 ),默认放到场景的位置为(0,0)

 例二:场景为QRectF(-200,-200,400,400),项目为(0,0,100,100)

    QGraphicsScene scene(-200,-200,400,400);//创建一个场景QGraphicsRectItem item1(0,0,100,100);//创建一个矩形scene.addItem(&item1);

 使用setPos()修改位置

    QGraphicsScene scene(-200,-200,400,400);//创建一个场景QGraphicsRectItem item1(0,0,100,100);//创建一个矩形scene.addItem(&item1);item1.setPos(-200,-200);//把位置设置为-200,-200

 修改项目:

例一:场景为QRectF(0,0,400,400),项目为(-50,-50,100,100)

将项目中的(0,0)点放到场景中的(0,0)点,由于项目的起始坐标为(-50,-50)宽高为(100,100),所以(0,0)点为项目的中心点

    QGraphicsScene scene(0,0,400,400);//创建一个场景QGraphicsRectItem item1(-50,-50,100,100);//创建一个矩形scene.addItem(&item1);

使用setPos()设置位置

    QGraphicsScene scene(0,0,400,400);//创建一个场景QGraphicsRectItem item1(-50,-50,100,100);//创建一个矩形scene.addItem(&item1);item1.setPos(50,50);//把位置设置为50,50

 

坐标的映射:

在处理场景中的项时,将坐标和任意形状从场景映射到项、从项映射到项或从视图映射到场景非常有用。

当你在QGraphicsView中点击鼠标时,可以通过QGraphicsView::mapToScene(),以及QGraphicsScene::itemAt()来获取光标下的图型项,获取在视图的一个椭圆形中包含的图形项,先传递一个QPainterPath参数给mapToScence()函数,然后传递映射后的路径给QGraphicsScene::items()函数。

图形视图框架中的映射函数:

QGraphicsView::mapToScence()从视图坐标系统映射到场景坐标系统
QGraphicsView::mapFromScene()从场景坐标系统映射到视图坐标系统
QGraphicsItem::mapToScene()从图形项的坐标系统映射到场景坐标系统
QGraphicsItem::mapToParent()从本图形项的坐标系统映射到其父图形项的坐标系统
QGraphicsItem::mapFromParent()从父图形项的坐标系统映射到本图形项的坐标系统
QGraphicsItem::mapToItem()从本图形项的坐标系统映射到另一个图形项坐标系统
QGraphicsItem::mapFromItem()从另一个图形项的坐标系统到本场景坐标系统

例子:

创建一个C++文件,继承自QGraphicsView,并重写鼠标点击事件

#ifndef MYVIEW_H
#define MYVIEW_H
#include
#include
#include
#include
#includeclass MyView:public QGraphicsView
{
public:MyView();void mousePressEvent(QMouseEvent *event);//鼠标点击事件
};#endif // MYVIEW_H#include "myview.h"MyView::MyView()
{}void MyView::mousePressEvent(QMouseEvent *event)//鼠标点击事件
{QPoint viewPos=event->pos();//获取鼠标在视图中的位置qDebug()<<"viewPos:"<itemAt(scenePos,QTransform());//获取该位置的项目if(item){QPointF itemPos=item->mapFromScene(scenePos);//获取项目在场景中的位置qDebug()<<"itemPos:"<
int main(int argc, char *argv[])
{QApplication a(argc, argv);QGraphicsScene scene(-200,-200,400,400);//创建一个场景QGraphicsEllipseItem item1(50,50,100,100);//圆项目scene.addItem(&item1);MyView view;//创建视图view.setScene(&scene);//添加场景view.show();return a.exec();
}

点击圆项目:

项目的堆叠顺序:

在QGraphicsItem中可以使用 setZValue()函数来设置堆叠的优先级,数值越大优先级越高,默认为0。

注意:优先级相同的话,后绘制的图形会覆盖先绘制的图形

优先级相同的情况: 

int main(int argc, char *argv[])
{QApplication a(argc, argv);QGraphicsScene scene(0,0,400,400);//创建一个场景QGraphicsEllipseItem item1(50,50,100,100);//圆项目item1.setBrush(QColor(Qt::red));//红色scene.addItem(&item1);QGraphicsEllipseItem item2(75,75,100,100);//圆项目item2.setBrush(QColor(Qt::blue));//蓝色scene.addItem(&item2);QGraphicsView view;view.setScene(&scene);//添加场景view.show();return a.exec();
}

 设置覆盖优先级:

int main(int argc, char *argv[])
{QApplication a(argc, argv);QGraphicsScene scene(0,0,400,400);//创建一个场景QGraphicsEllipseItem item1(50,50,100,100);//圆项目item1.setBrush(QColor(Qt::red));item1.setZValue(1);//设置覆盖优先级scene.addItem(&item1);QGraphicsEllipseItem item2(75,75,100,100);//圆项目item2.setBrush(QColor(Qt::blue));scene.addItem(&item2);QGraphicsView view;view.setScene(&scene);//添加场景view.show();return a.exec();
}

设置父项目:

QGraphicsItem可以设置父项目,使用setParentItem()函数可以将一个项设置成另一个项的父项。如果此项目已有父项,则首先将其从上一个父项中删除。

parentItem()返回父项
parentObject()返回指向项的父项的指针,强制转换为 QGraphicsObject
parentWidget()返回指向项的父构件的指针。项目的父微件是最接近的父微件
int main(int argc, char *argv[])
{QApplication a(argc, argv);QGraphicsScene scene(0,0,400,400);//创建一个场景QGraphicsEllipseItem item1(75,75,100,100);//圆项目item1.setBrush(QColor(Qt::red));scene.addItem(&item1);QGraphicsEllipseItem item2(75,75,200,200);//圆项目item2.setBrush(QColor(Qt::blue));scene.addItem(&item2);item1.setParentItem(&item2);//设置父项QGraphicsView view;view.setScene(&scene);//添加场景view.show();return a.exec();
}

视图的中心:

当场景很大时,可以使用QGraphicsView中的centerOn()函数来设置场景中的一个点或一个图形项作为视图的显示中心

未设置中心:

int main(int argc, char *argv[])
{QApplication a(argc, argv);QGraphicsScene scene(-200,-200,800,800);//创建一个场景QGraphicsEllipseItem item1(75,75,100,100);//圆项目item1.setBrush(QColor(Qt::red));scene.addItem(&item1);QGraphicsView view;view.setScene(&scene);//添加场景//view.centerOn(&item1);//设置中心图形项view.resize(400,400);view.show();return a.exec();
}

 设置中心后:

int main(int argc, char *argv[])
{QApplication a(argc, argv);QGraphicsScene scene(-200,-200,800,800);//创建一个场景QGraphicsEllipseItem item1(75,75,100,100);//圆项目item1.setBrush(QColor(Qt::red));scene.addItem(&item1);QGraphicsView view;view.setScene(&scene);//添加场景view.centerOn(&item1);//设置中心图形项view.resize(400,400);view.show();return a.exec();
}

参考文档:

Graphics View Framework | Qt Widgets 5.15.13

相关内容

热门资讯

阿里春招-2023.3.15-... 极差三元组计数 Problem Description 给定一个数组,请你计算有多少个...
电压放大器在钢筋剥离损伤识别试...   实验名称:钢筋剥离损伤识别试验  研究方向:无损检测  测试目的&#...
MOCO论文前几段精读 MoCo MoCo是CVPR 2020的最佳论文提名,算是视觉领域里,使...
【lua初级篇】基础知识和开发... 文章介绍 文章介绍 简述 工具安装配置和下载 快速看基础知识 一些常用的关键字一览 数据类型 tab...
Yuv422、Nv12转C#B... 1.1、Nv12转Bitmapint w = 1920;int h = 1080;i...
Linux互斥量和信号量的区别... 互斥量和信号量的区别 1.互斥量用于线程的互斥: 互斥:加锁解锁,是指某...
Git 和 GitHub 超入... 1.解决行结束符问题 需要在你的仓库中添加一个.gitattributes文件,标记正...
基于C++的AI五子棋游戏项目... 项目资源下载 基于C++的AI五子棋游戏项目源码压缩包下载地址基于C+...
#浅聊 webSocket (... 如果可以实现记得点赞分享,谢谢老铁~ 一,什么是webso...
Java SE API kno... Java SE API know how 字符串 紧凑字符串 java8 无论字符串的编码ÿ...
常用的VB函数 数学函数函数说明示例Sin(N)返回自变量N的正弦值Sin(0)=0 N为弧度Cos(N)返...
C++ 机房预约系统(五):管... 7.3 显示功能 功能描述: 显示学生信息或教师信息 功能实现: voi...
PIC单片机的一些问题 error 1347 can't find 0x16 words (0x16 withtotal) ...
完美日记母公司再度携手中国妇基... 撰稿 | 多客 来源 | 贝多财经 当春时节,梦想花开。和煦的三月暖阳,...
GDPU C语言 天码行空3 1. 分段函数 #includeint main(){double x,y;scanf("%lf",...
【瑞萨 MCU】开发环境搭建之... e2 studio e2 studio(简称为 e2 或 e2s)是瑞萨...
C语言内联汇编 之前我们介绍了一种C语言与汇编代码混合编程方式,就是两个文件分开编写,分...
Linux 网络编程学习笔记—... 一、TCP 服务的特点 传输层协议主要有 TCP 协议和 UDP 协议,前者相对于后者...
KubeSphere All ... KubeSphere All in one安装配置手册 1. 初始化 1.1 配置apt源 # vi...
学习软件测试怎么能缺少练手的软... 你好,我是凡哥。 最近收到许多自学自动化测试的小伙伴私信,学习了理论知识...
【面试题】浅谈css加载是否会... 大厂面试题分享 面试题库前后端面试题库 (面试必备) 推荐:...
直播带货系统开发的关键点、代码... 时下,直播的热度依然不减,而它的产物之一:直播带货系统&#...
一文读懂强化学习! 一.了解强化学习1.1基本概念强化学习是考虑智能体(Agent)与环境&...
Spring Cloud之一:... 目录 环境 Eureka工程的创建步骤 系列目录(持续更新。。。) S...
golang实现守护进程(2) 前言golang实现守护进程,包含功能:1. 守护进程只创建一次2. 平...
url 格式详解 统一资源定位系统(uniform resource locator; url ...
elasticsearch7.... elasticsearch版本:7.17.3 目标:实现对类型为text...
SpringBoot 加载系统... 开发环境: IDEA 2022.1.4+ MyBatis         代码参考:spri...
交换机概念和知识和命令 目录 一、华为交换机基础学习的一些重要概念和知识 二、交换机常用命令大全 三、不常用的交换机命令 ...
什么是 JavaScript ... 本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻࿰...