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

2023-12-15 17:52:04

参考:

  1. https://zhuanlan.zhihu.com/p/584048811
  2. https://www.zhihu.com/tardis/zm/art/634951149?source_id=1005

小谈Qt的坐标系系统

Qt中有三个坐标系

  • 设备坐标系
  • 窗口坐标系
  • 逻辑坐标系

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

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

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

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

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

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

直接看下图

在这里插入图片描述在这里插入图片描述via https://doc.qt.io/qt-6/coordsys.html#window-viewport-conversion

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

废话不多说
还是按照我的方式 & Qt的官方文档来讲吧

我自己的例子

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

在这里插入图片描述平时我们的三个坐标系都是相同的,都是水平方向是X轴,垂直方向是Y轴,坐标原点是左上角(0, 0)。

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

即如图所示
在这里插入图片描述那么三个坐标系的变化流程就是

在这里插入图片描述还是先上个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);
}

那么表现
在这里插入图片描述这里可以先重点说下
我们以普通用户(程序员)的角度来理解这个代码。因为有三个坐标系,所以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);
}

这时候我们的窗口就变成了这个样子。
在这里插入图片描述也就是说,我的物理大小,并没有变,我通过更改逻辑坐标,(放大两倍的效果) 看起来将我的整个坐标系变大了。比如原来我可以通过

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

来绘制对角。

经过

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

最后

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

在这里插入图片描述如果还想绘制对角,那么就得

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

在这里插入图片描述也就是,我们现在将用户的坐标系放大了两倍。这个就是setWindow的作用。

setViewport()
大家可以理解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);
}

大家可以看现象,画线也变粗了。这是为啥呢?
在这里插入图片描述很简单,painter.setViewport(0, 0, 1000, 1000)这个代码相当于把整个物理坐标系翻倍了。也就是单位逻辑坐标变大了。

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

所以会有两个现象

  • 画线变粗
  • drawLine现在只需要一半就可以撑满整个窗口。

小结:

在这里插入图片描述还是要好好观察下这个顺序。

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

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

然后通过setWindow放大坐标系

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

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

文章来源:https://blog.csdn.net/qq_35662333/article/details/134924726
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。