QT 窗口与视口(setWindow/setViewPort)的一些理解与整理

2023-10-27


  QPainter.drawRect(QRectF)绘制图形传入的是世界坐标,而后经过变换矩形变为窗口坐标,最后经过窗口-视口变换变为设备坐标。其中世界坐标系和窗口坐标系都属于逻辑坐标系,设备坐标系属于物理坐标。


世界坐标、窗口坐标和设备坐标

-   世界坐标

  世界坐标也叫逻辑坐标,使用的单位叫做逻辑单位,在世界坐标系中的大小与显示设备大小无关,类似于数学中的单位长度。

-   窗口坐标

  窗口坐标与世界坐标差在坐标变换上,如translate、rotate、scale、shear等。

-   设备坐标

  设备坐标是物理坐标,设备的左上角为原点,向右为x正方向,向下为y轴正方向。显示器中,坐标单位通常为像素,打印机中,坐标单位通常为点。

  综上,三个坐标系中,世界坐标系和窗口坐标系是逻辑坐标系,与具体的设备大小没有关系,两者之间相差的是坐标变换

窗口和视口

-   窗口

  窗口是窗口坐标系中的矩形框,窗口存在的意义是为了确定显示窗口坐标系中的哪部分区域。

  使用painter.setWindow(x,y,w,h)即可设置窗口的大小以及坐标系原点在窗口中的位置。默认情况下窗口与视口大小相同,并且原点都位于左上角。

-   视口

  视口是设备环境中的一个矩形框,使用物理坐标,和设备大小密切相关,超出设备外的视口区域不予显示(**需要理解下,超出视口区域,但是没有超出设备外也是可以显示的**)。视口存在的意义是为了将显示的内容显示在物理坐标系中的哪个矩形区域。

  使用painter.setViewPort(x,y,w,h)即可设置视口的大小以及视口在物理坐标系中的位置。


世界变换和窗口视口变换

-   世界变换

  世界变换的目的是直接对逻辑坐标进行矩阵变换,常见的有translate、scale、rotate、shear。

-   窗口视口变换

  用户输入的坐标一定是逻辑坐标,最终用来绘制的一定是经过窗口-视口变换后的视口坐标,也就是设备坐标(物理坐标)。

  如果不显示使用setViewPort和setWindow指定视口和窗口大小,默认的窗口和视口坐标原点都是(0,0),窗口和视口大小都是设备的长和宽。若设置了一个,那么未设置的仍然使用默认设置。


QPainter::setWindow 修改了窗口位置和大小(**左上角重新定义了一个数值和长度,切记不是像素,是一个逻辑单位,存在跟视口的换算**)

QPainter::setViewport 修改了视口位置和像素个数(左上角移动到相应位置和像素个数)


窗口和视口变换关系实际上就是一对线性函数:

`X' = aX + b`

`Y' = cY + d`

其中,XY为窗口坐标,X'Y'为视口坐标。距离说明:

如果不显示的用代码指定窗口和视口的大小,默认的窗口和视口坐标原点都是(0,0),大小都是设备的长和宽。用代码指定窗口和视口大小的方式分别为:

setWindow(-300,-300,600,600)// 指定窗口位置和大小

setViewPort(-100,-100,600,600)// 指定视口位置和大小。

窗口和视口的变换关系其实就是一对线性函数。

X'=aX+b;

Y'=cY+d。

其中,a,b,c,d为四个待确定的系数,X、Y是窗口坐标,X'、Y'是视口坐标。a,b,c,d如何确定?在窗口(-300,-300,600,600)中,实际上是指定了窗口的两个坐标,左上角(-300,-300),右下角(300,300);在视口(-100,-100,600,600)中,指定了视口左上角坐标(-100,-100),视口右下角(500,500).根据左上角对应左上角,右下角对应右下角的关系,得到:

x方向有:-100=-300a+b,500=300a+b,解得a=1,b=200;

y方向有:-100=-300c+d,500=300c+d,解得c=1,d=200。

得到关系后再来绘图则是经过该关系变换后的值了。比如painter.drawPoint(0,10),对应x=0,得到x'=0*a+b=200;对应y=10,得到y'=10*c+d=210;即实际上是在显示设备的(200,210)处绘制了一个点

示例:

  

````
{

   ui->graphicsView->scale(0.95,0.95);
   painter.save();
   painter.setPen(Qt::red);
   painter.drawRect(0,0, 200, 200);//可视化视口(红色)

   painter.setViewport(0,0, 200, 200);

   QPen pen = painter.pen();
   pen.setStyle(Qt::DashLine);
   pen.setWidth(3);
   pen.setColor(Qt::blue);
   painter.setPen(pen);
   painter.setWindow(-100, -100, 200, 200);

   painter.drawRect(-100, -100, 200, 200);//可视化窗口(蓝色)
   painter.translate(50, 50);//平移(50,50)
   painter.setPen(Qt::black);//绘制两个图形
   painter.drawRect(-100, -100, 100, 100);

   painter.drawRect(50, 50, 100, 100);
   painter.restore();

}
````


![92-698792123.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c82c589f8bf846219e5efce562f1b03c~tplv-k3u1fbpfcp-watermark.image?)


1.  视口setViewport(QRectF)传入的是QWidget的物理坐标,窗口setWindow(QRectF)传入的是逻辑坐标。视口和窗口是线性映射关系,因此蓝框和红色框会重合。
2.  平移translate(50,50)操作,移动的是逻辑坐标系,原来的坐标系原点在蓝色窗口中央,平移后位于图示的红色坐标系。
3.  save和restore用于保存和恢复QPainter的变换。

  

一、窗口和视口

世界坐标系中要显示的区域(通常在观察坐标系内定义)称为窗口。

窗口映射到显示器(设备)上的区域称为视口(或称视区)。

窗口定义显示什么;视口定义在何处显示

如何将窗口内的图形在视口中显示出来呢?

必须经过将窗口到视口的变换处理,这种变换就是观察变换(Viewing Transforma)。

二、观察变换

1、变焦距效果

当窗口变小时,由于视口大小不变,就可以放大图形对象的某一部分,从而观察到在较大的窗口时未显示出的细节。

而当窗口变大,视口不变时,视口内显示的内容不断变小。

类似于照相机的变焦处理。

2、整体缩放效果

当窗口大小不变而视口大小发生变化时,得到整体放缩效果。这种放缩不改变观察对象的内容。

如果把一个固定大小的窗口在一幅大图形上移动,时空不变,会产生什么效果?

漫游效果!
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT 窗口与视口(setWindow/setViewPort)的一些理解与整理 的相关文章

  • 在 Web 浏览器中禁用 F5 [重复]

    这个问题在这里已经有答案了 可能的重复 禁用浏览器的后退按钮 https stackoverflow com questions 961188 disable browsers back button 如何禁用浏览器上的 F5 刷新 htt
  • 从 Invoke 方法获取 RETURN

    我正在尝试从另一个线程上的列表框项目中读取值 我尝试创建一种新方法来运行调用命令 我可以设法将命令发送到列表框 例如通过调用方法添加 但我似乎无法得到响应 我似乎无法获取该项目的值 我尝试了几种方法 一旦我将它从空变为字符串 事情就开始变得
  • 使用 Xamarin.Forms 和 Zxing 生成 QR 码

    我在网上看到了很多关于这个的内容 旧帖子 但似乎没有什么对我有用 我正在尝试从字符串中生成二维码并将其显示在应用程序中 这就是我一开始的情况 qrCode new ZXingBarcodeImageView BarcodeFormat Ba
  • 为什么在 C++ 中声明枚举时使用 typedef?

    我已经很多年没有写过任何 C 了 现在我正试图重新开始 然后我遇到了这个并考虑放弃 typedef enum TokenType blah1 0x00000000 blah2 0X01000000 blah3 0X02000000 Toke
  • 以下 PLINQ 代码没有改进

    我没有看到使用以下代码的处理速度有任何改进 IEnumerable
  • 为什么 C# 中同一类型的隐式和显式运算符不能共存? [复制]

    这个问题在这里已经有答案了 为什么同一类中两个相同类型的运算符 显式和隐式 不能共存 假设我有以下内容 public class Fahrenheit public float Degrees get set public Fahrenhe
  • C# Winforms Designer 无法打开,因为它无法在同一程序集中找到类型

    我收到以下错误 找不到类型 My Special UserControl 请确保引用包含此类型的程序集 如果此类型是您的开发项目的一部分 请确保已使用当前平台或任何 CPU 的设置成功构建该项目 但没有任何意义的是My Special Us
  • 判断串口是普通COM还是SPP

    我正在寻找一种方法来确定 COM 是标准 COM 还是 SPP COM 也称为 COM 设备的电缆替换蓝牙适配器 我有一个可以在 USB COM gt USB 和蓝牙下工作的设备 并且蓝牙接口可以与 SPP 一起工作 我目前正在使用Syst
  • 为什么 std::function 不是有效的模板参数,而函数指针却是?

    我已经定义了名为的类模板CallBackAtInit其唯一目的是在初始化时调用函数 构造函数 该函数在模板参数中指定 问题是模板不接受std function作为参数 但它们接受函数指针 为什么 这是我的代码 include
  • “没有合适的默认构造函数可用”——为什么会调用默认构造函数?

    我已经查看了与此相关的其他一些问题 但我不明白为什么在我的情况下甚至应该调用默认构造函数 我可以只提供一个默认构造函数 但我想了解它为什么这样做以及它会产生什么影响 error C2512 CubeGeometry no appropria
  • 编写具有多种类型的泛型扩展方法时的类型推断问题

    我正在为 IEnumerable 编写一个通用扩展方法 用于将对象列表映射到另一个映射对象列表 这就是我希望该方法的工作方式 IList
  • 在 C 语言中替换宏内的宏

    我正在尝试使代码部分可重用 我下面的评论片段没有达到我想要的效果 define NAME ABC define LOG SIZE NAME LEN 我想LOG SIZE决心ABC LEN 我尝试过使用 但没能让它发挥作用 LOG SIZE在
  • MSChart 控件中的自定义 X/Y 网格线

    我有一个带有简单 2D 折线图的 C Windows 窗体 我想向其中添加自定义 X 或 Y 轴标记 并绘制自定义网格线 例如 以突出显示的颜色 虚线 我查看了 customLabels 属性 但这似乎覆盖了我仍然想显示的默认网格 这是为了
  • WinForms - 加载表单时如何使用 PaintEventArgs 运行函数?

    我试图理解图形 在 Graphics FromImage 文档中 它有这样的示例 private void FromImageImage PaintEventArgs e Create image Image imageFile Image
  • WPF DataGrid - 在每行末尾添加按钮

    我想在数据网格的每一行的末尾添加一个按钮 我找到了以下 xaml 但它将按钮添加到开头 有人知道如何在所有数据绑定列之后添加它吗 这会将按钮添加到开头而不是末尾
  • 不使用放置 new 返回的指针时的 C++ 严格别名

    这可能会导致未定义的行为吗 uint8 t storage 4 We assume storage is properly aligned here int32 t intPtr new void storage int32 t 4 I k
  • 时间:2019-03-17 标签:c#TimerStopConfusion

    我想通过单击按钮时更改文本颜色来将文本框文本设置为 闪烁 我可以让文本按照我想要的方式闪烁 但我希望它在闪烁几次后停止 我不知道如何在计时器触发几次后让它停止 这是我的代码 public Form1 InitializeComponent
  • PyQt5:如何使QThread返回数据到主线程

    I am a PyQt 5 4 1 1初学者 我的Python是3 4 3 这是我尝试遵循的many https mayaposch wordpress com 2011 11 01 how to really truly use qthr
  • 值和类型的简洁双向静态 1:1 映射

    我将从我想象如何使用我想要创建的代码开始 它不必完全像这样 但它是我在标题中所说的 简洁 的一个很好的例子 就我而言 它是将类型映射到相关的枚举值 struct bar foo
  • IDisposable 的显式实现

    虽然有很多关于IDisposable在 SO 上找到 我还没有找到答案 我通常遵循这样的做法 当我的一个班级拥有一个IDisposable对象然后它也实现IDisposable并打电话Dispose在拥有的对象上 然而最近我遇到了一个类 它

随机推荐

  • 数制转换(数据结构课程设计C语言版)

    define CRT SECURE NO WARNINGS include
  • 51单片机——定时器

    51单片机 定时器 为什么使用定时器 定时器原理 定时器设置 中断配置 源代码 为什么使用定时器 之前我们的led灯每隔1s循环左移点亮的时候 使用的定时方法是在c程序执行若干次空循环 这样会耗费很多cpu资源 因为空轮询 本篇博客将使用5
  • epoll使用(服务端代码讲解)

    下面这段代码是一个回射服务器 它会把客户端发送给它的信息再返回给客户端 include
  • Python的深浅拷贝

    目录 一 可变对象和不可变对象 二 概念 三 深浅拷贝 1 浅拷贝 2 深拷贝 一 可变对象和不可变对象 可变类型 列表 字典 集合 不可变类型 整数 小数 复数 字符串 元组 二 概念 是指向引用 浅拷贝 只拷贝父对象 不拷贝子对象 深拷
  • 数据库初始化过程

    从数据文件到内存的初始化过程 SQL gt startup mount ORACLE 例程已经启动 Total System Global Area 1970937856 bytes Fixed Size 2191096 bytes Var
  • 详解netty长连接网关请求处理模型

    想要支持海量的客户端请求 首先要有一套高效的请求处理模型 本文以开源项目SONA为例 详解如何基于netty设计请求处理模型 帮助读者动手实践 本文最后附上开源项目地址 背景 Sona 平台是一个搭建语音房产品的全端解决方案 包含了房间管理
  • 【Pytorch Lighting】第 8 章:自监督学习

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • 第52节:cesium 3DTiles模型特效+选中高亮(含源码+视频)

    结果示例 完整源码
  • PAT_Basic_Level

    PAT乙级 1001 害死人不偿命的 3n 1 猜想 1002 写出这个数 1003 我要通过 1004 成绩排名 1005 继续 3n 1 猜想 1006 换个格式输出整数 1007 素数对猜想 1008 数组元素循环右移问题 1009
  • 今天已更新!Awesome AIGC与GPT加入免费镜像、相关插件、相关网页、相关项目源码等内容...

    点击上方 Python与机器智能 选择 星标 公众号 第一时间获取价值内容 目前这个文档经过好多天的收集和整理 给大家带来最全的AIGC与GPT资料大全 数百个链接和pdf 文档本身有近20页 主要包涵资源资料分享 gpt AI绘画相关技术
  • Feign远程调用的底层方法逻辑

    今天在写业务的时候 需要通过feign调用远程接口 平常只是调用就行了 没有了解到他是如何代码实现的 今天就使用debug来解开feign为什么可以远程调用的面纱 希望看本文章的同学朋友们 可以自己写一个简单的远程调用方法跟着我一起走一遍d
  • No.13 免费音乐软件推荐:轻松畅听全网音乐

    这些开源音乐软件为用户提供了丰富的音乐搜索和播放功能 让您可以享受高品质的音乐畅听体验 它们支持多种音乐平台 如网易云音乐 QQ音乐 酷狗音乐等 同时提供了自动切换播放源 精选歌单 数据同步等实用功能 选择这些项目 您将能够轻松搜索 播放和
  • C/C++ 语言实现使用LU分解求解线性方程组

    应用计算方法C语言程序 02 接应用计算方法C语言程序 01 C C 语言实现矩阵LU分解 Doolittle A 以计算方法课本例题4 6为例 设矩阵A b分别为 A 3 3 1 3 3 2 1 1 2 3 4 b 3 1 2 1 利用C
  • oracle随机数 — dbms_random

    oracle随机数 dbms random ORACLE的PL SQL提供了生成随机数和随机字符串的多种方式 罗列如下 1 小数 0 1 select dbms random value from dual more 2 指定范围内的小数
  • fseek用法:int fseek(FILE *stream, long offset, int origin);

    1 SEEK SET 从文件开头开始定位 参数必须大于0 2 SEEK CUR 从文件当前位置开始定位 参数可正可负 3 SEEK END 从文件末尾开始定位 参数必须小于0 include
  • (附源码)springboot自习室座位预约系统 毕业设计674156

    springboot自习室座位预约系统 摘要 在社会快速发展的影响下 教育事业蓬勃发展 大大增加了学校的数量 多样性 教育质量等要求 使教育的管理和运营比过去更加困难 依照这一现实为基础 设计一个快捷而又方便的自习室座位预约系统是一项十分重
  • 判断聚类 n_clusters

    目录 基本原理 代码实现 肘部法则 Elbow Method 轮廓系数 Silhouette Coefficient Gap Statistic 间隙统计量 Calinski Harabasz Index Calinski Harabasz
  • js中对new Date() 中转换字符串方法toLocaleString的使用。

    提供特定于区域设置的日期和时间格式 dateTimeFormatObj new Intl DateTimeFormat locales options dateTimeFormatObj 必需 将 DateTimeFormat 对象分配到的
  • 《C++ Primer Plus》第四章 复合类型 4.12复习题答案

    1 char actor 30 0 short bstsie 100 0 float chuck 13 0 long double dipsea 64 0 2 array
  • QT 窗口与视口(setWindow/setViewPort)的一些理解与整理

    QPainter drawRect QRectF 绘制图形传入的是世界坐标 而后经过变换矩形变为窗口坐标 最后经过窗口 视口变换变为设备坐标 其中世界坐标系和窗口坐标系都属于逻辑坐标系 设备坐标系属于物理坐标 世界坐标 窗口坐标和设备坐标