首页 > 其他分享 >小谈Qt的坐标系系统 - 3个坐标系,2个变换

小谈Qt的坐标系系统 - 3个坐标系,2个变换

时间:2023-09-04 15:44:30浏览次数:79  
标签:逻辑 Qt 小谈 坐标系 500 setWindow painter

小谈Qt的坐标系系统

Qt中有三个坐标系

设备坐标系

窗口坐标系

逻辑坐标系

设备坐标系: 即Device坐标系。也是物理坐标系。即真实的的物理坐标系。

逻辑坐标系: 即用户坐标系。也就是说日常大家使用Qt的时候的坐标系。

窗口坐标系: 这个坐标系是QPainter设置setWindow以后的一个坐标系。

这三个坐标系,基本上就代表了常规的绘制引擎的三个坐标系。

那么三个坐标系,就代表可以用两次变换来实现了。

这个就是QPainter中的setWindow() & setViewport()的两个概念了

直接看下图

 

<img src="https://pic2.zhimg.com/v2-48e08b23b4413e7059b814bc90f29b71_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="437" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic2.zhimg.com/v2-48e08b23b4413e7059b814bc90f29b71_r.jpg"/>

 

 

The viewport represents the physical coordinates specifying an arbitrary rectangle. The "window" describes the same rectangle in logical coordinates. By default the logical and physical coordinate systems coincide, and are equivalent to the paint device's rectangle.

 

视口表示指定任意矩形的物理坐标。“窗口”在逻辑坐标中描述了相同的矩形。默认情况下,逻辑坐标系和物理坐标系重合,并且等同于绘制设备的矩形。

via https://doc.qt.io/qt-6/coordsys.html#window-viewport-conversion

OK,既然有了这些概念,那么我们就开始讲一下,坐标系的转换流程。

其实,一开始我准备从网上copy一份教程来讲的,但是发现大家讲的全是tm不明不白的。所以这里我决定自己来讲了

废话不多说

还是按照我的方式 & Qt的官方文档来讲吧

我自己的例子

画个图,描述下这三个坐标系

 

<img src="https://pic1.zhimg.com/v2-bddaf11528d32a9e4a24dc0d0ac58fd4_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="608" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic1.zhimg.com/v2-bddaf11528d32a9e4a24dc0d0ac58fd4_r.jpg"/>

 

 

平时我们的三个坐标系都是相同的,都是水平方向是X轴,垂直方向是Y轴,坐标原点是左上角(0, 0)。

 

X轴从左到右增加,Y轴从上到下增加

即如图所示

 

<img src="https://pic4.zhimg.com/v2-b01f30d2835ca3e44807b5612859bd67_b.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="608" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://pic4.zhimg.com/v2-b01f30d2835ca3e44807b5612859bd67_r.jpg"/>

 

 

那么三个坐标系的变化流程就是

 

逻辑坐标系->setWindow()->窗口坐标系->setViewport()->设备坐标系

还是先上个Qt的Demo

Qt的Demo

设定,屏幕的DPI是96

三个坐标系重叠

先创建一个QWidget,然后设置其大小是(500, 500)

resize(500,500);

然后再重写他的PaintEvent事件

void QtWidgetsApplication1::paintEvent(QPaintEvent*e)

{

QPainter painter(this);

painter.drawLine(0,0,500,500);

}

那么表现

 

<img src="https://pic1.zhimg.com/v2-c0fe3fea97c20cdd725598b40462ab48_b.jpg" data-caption="" data-size="normal" data-rawwidth="503" data-rawheight="531" class="origin_image zh-lightbox-thumb" width="503" data-original="https://pic1.zhimg.com/v2-c0fe3fea97c20cdd725598b40462ab48_r.jpg"/>

 

 

 

这里可以先重点说下

我们以普通用户(程序员)的角度来理解这个代码。因为有三个坐标系,所以Qt的代码全都是以逻辑坐标系为基础的。对于这个代码来讲

painter.drawLine(0,0,500,500);

drawLine的时候实际上就是以逻辑坐标系为准。这时候,三个坐标系是相等的,没有任何比例变化。大家可以理解为这三个坐标系是重叠的。

setWindow()

控制变量,其他的代码不变,我们只单独设置setWindow这个代码setWindow的作用,就是在物理坐标系不变的情况下,将逻辑坐标系进行缩放。

假定,我们的代码是这样的。将逻辑坐标扩大一倍,那么代码就是这样的

void QtWidgetsApplication1::paintEvent(QPaintEvent*e)

{

QPainter painter(this);

painter.setWindow(0,0,1000,1000);

painter.drawLine(0,0,500,500);

}

这时候我们的窗口就变成了这个样子。

 

<img src="https://pic4.zhimg.com/v2-7c75f310b08bb8d21905ae2dab4ab0af_b.jpg" data-caption="" data-size="normal" data-rawwidth="500" data-rawheight="532" class="origin_image zh-lightbox-thumb" width="500" data-original="https://pic4.zhimg.com/v2-7c75f310b08bb8d21905ae2dab4ab0af_r.jpg"/>

 

 

也就是说,我的物理大小,并没有变,我通过更改逻辑坐标,(放大两倍的效果) 看起来将我的整个坐标系变大了。比如原来我可以通过

painter.drawLine(0,0,500,500);

来绘制对角。

经过

painter.setWindow(0,0,1000,1000)\\放大逻辑坐标系两倍

最后

painter.drawLine(0,0,500,500);\\只能绘制一半的效果。

 

 

<img src="https://pic4.zhimg.com/v2-7c75f310b08bb8d21905ae2dab4ab0af_b.jpg" data-caption="" data-size="normal" data-rawwidth="500" data-rawheight="532" class="origin_image zh-lightbox-thumb" width="500" data-original="https://pic4.zhimg.com/v2-7c75f310b08bb8d21905ae2dab4ab0af_r.jpg"/>

 

 

如果还想绘制对角,那么就得

painter.drawLine(0,0,1000,1000);

 

 

<img src="https://pic2.zhimg.com/v2-7bdda7da0a7b5cf8b7e62dc0a8e625a1_b.jpg" data-caption="" data-size="normal" data-rawwidth="895" data-rawheight="544" class="origin_image zh-lightbox-thumb" width="895" data-original="https://pic2.zhimg.com/v2-7bdda7da0a7b5cf8b7e62dc0a8e625a1_r.jpg"/>

 

 

也就是,我们现在将用户的坐标系放大了两倍。这个就是setWindow的作用。

setViewport()

大家可以理解setViewport的作用就是控制物理坐标系的。

实际上,不管是Qt的官方文档,还是网上的例子,实际上setViewport的设置都是变化的,这样就很难给新手理解了。

比如官方代码

int side=qMin(width(),height());

int x=(width()-side/2);

int y=(height()-side/2);

 

painter.setViewport(x,y,side,side); 

还要控制窗口的宽高,这时候就更难理解了。我的例子还是控制变量,假定Window不变。我们只更改ViewPort

还是那个例子,窗口大小(500, 500)。我们还是画对角线。这时候我们把代码改成

void QtWidgetsApplication1::paintEvent(QPaintEvent*e)

{

QPainter painter(this);

painter.setViewport(0,0,1000,1000)

painter.drawLine(0,0,250,250);

}

大家可以看现象,画线也变粗了。这是为啥呢?

 

<img src="https://pic3.zhimg.com/v2-f46c7384b0871a3f5cca74276b1feb3e_b.jpg" data-caption="" data-size="normal" data-rawwidth="500" data-rawheight="533" class="origin_image zh-lightbox-thumb" width="500" data-original="https://pic3.zhimg.com/v2-f46c7384b0871a3f5cca74276b1feb3e_r.jpg"/>

 

 

很简单,painter.setViewport(0, 0, 1000, 1000)这个代码相当于把整个物理坐标系翻倍了。也就是单位逻辑坐标变大了。

 

原来逻辑坐标画1个像素点,现在相当于画2个。

所以会有两个现象

画线变粗

drawLine现在只需要一半就可以撑满整个窗口。

小结:

逻辑坐标系->setWindow()->窗口坐标系->setViewport()->设备坐标系

还是要好好观察下这个顺序。

Qt通过三个坐标系,来做到了窗口之间的变换 & 放大缩小。

那么工程上是如何使用的呢。一般来说viewport这个跟当前物理DPI保持一致。

然后通过setWindow放大坐标系

 

如果你想把整个逻辑坐标系放大。那么就用setWindow()还是看你当前的逻辑需求- 即逻辑坐标系的需求。

以这个为出发点,那么再去理解setWindow & setViewport就很好理解了。

 

 

from:https://zhuanlan.zhihu.com/p/584048811

标签:逻辑,Qt,小谈,坐标系,500,setWindow,painter
From: https://www.cnblogs.com/im18620660608/p/17677235.html

相关文章

  • QT坐标系转换(将QPainter左上角为原点的坐标系转换为正常坐标系)
    没有复杂的变换,简单转化窗口坐标系,即可按我们正常熟知的坐标系进行绘图QPainter坐标系以左上角为原点,如下图 在这样的坐标系下绘图,位置这是倒过来的QPainterm_pPainter(this);   m_pPainter.setBrush(Qt::yellow);   m_pPainter.drawRect(0,0,50,50);   m......
  • VS+Qt工具vsaddin
    1.https://download.qt.io/official_releases/vsaddin/2.ToolsExtensions-VisualStudio 安装:C:\xxxx\VSIXInstaller.exexxx.vsix......
  • 【Qt初入江湖】Qt QSqlQueryModel 底层架构、原理详细描述
    鱼弦:全栈领域创作新星创作者、51CTO(Top红人+专家博主)、github开源爱好者(go-zero源码二次开发、游戏后端架构https://github.com/Peakchen) QtQSqlQueryModel是Qt中用于实现自定义SQL查询的模型类,它继承自QAbstractTableModel。QSqlQueryModel封装了对数据库查询结果的处理,可......
  • 【Qt初入江湖】Qt QSqlRelationalDelegate 底层架构、原理详细描述
    鱼弦:全栈领域创作新星创作者、51CTO(Top红人+专家博主)、github开源爱好者(go-zero源码二次开发、游戏后端架构https://github.com/Peakchen) Qt的QSqlRelationalDelegate类是用于在Qt模型/视图框架中使用带有外键关系的数据库表格数据的委托类。它提供了一组用于在表格视图......
  • Qt中两个QLabel标签控件重叠的方法
       在项目中遇到这样的问题,需要开发一个电池控件,显示电量同时又能以数字标注电量的多少。效果如下图所示:      通常在Qt中图片的显示是用的QLabel标签控件。根据以往MFC开发的经验,想当然的是两个标签控件重叠排放,下面的标签控件显示图片,上面的标签控件显示数字。但......
  • 记录centos stream 9 编译qt5.15.10源码
    开始装的一些依赖库没有记录gcc之类的,都是通过dnf安装的主要是make过程中出现的问题(qtwebengine)及其如何解决编译的命令如下./configure-prefix/home/kun/usr/Qt/5.15.10-opensource-confirm-licensemake-j16makeinstallconfigure阶段失败一般都是缺少,都是dnf解决的......
  • ESP8266透明串口转MQTT模块使用说明
    ESP8266透明串口转MQTT模块使用说明 更新历史日期撰写备注2023.9.2YTH       目录1    模块功能...22    串口驱动...23    快速验证功能...33.1    模块默认功能:...33.2    手机开启热点.......
  • Qt编译报错:multiple definition of
    解决方法一:在.pro文件下查看SOURCES+=和HEADERS+=也没有重复引入文件,删除重复的文件即可。解决方法二:把debug文件夹下的.o文件都删除,然后再编译下。解决方法三:如果.h文件中有类的定义和实现,则实现时在每个成员前加inline。  转载于:QT项目出现multipledefinitionof错误......
  • qt读取json文件
    Qt读取json数据文件步骤:本条记录未进行判断,只是针对自己在已知json数据文件下的读取1、打开文件QFliefile("设置路径");2、设置文件打开方式file.open(QFile::ReadOnly|WriteOnly|ReadWrite);3、读取文件数据QByteArrayall=file.readAll();4、关闭文件file.cl......
  • Qt绘制3D图形例程
    本文主要内容是关于QOpenGLWidget的使用。此控件用于代替旧的QGLWidget类。关于此类的使用方法可以参考Qt帮助相关内容。glDrawArrays(...)函数参数说明:OpenGL理解GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN等绘制三角形序列的三种方式_匆忙拥挤repeat的博客-CSDN博客变量修饰符说明......