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

QPainter在绘制图形时涉及世界坐标、窗口坐标和设备坐标的转换。世界坐标和窗口坐标是逻辑坐标系,不受设备尺寸影响,设备坐标是物理坐标。窗口定义显示内容,视口定义显示位置。窗口和视口通过线性变换关联,可以实现变焦距和整体缩放效果。通过setWindow和setViewport方法可调整窗口和视口的位置与大小。
摘要由CSDN通过智能技术生成


  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、整体缩放效果

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

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

漫游效果!
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值