窗口坐标为逻辑坐标,是基于视口坐标系的。

视口坐标为物理坐标,是基于绘图设备坐标系的

窗口坐标始终以视口坐标为最终目标进行映射

QPainter::setWindow 修改了窗口位置和大小(左上角重新定义了一个数值和长度)

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

------------------------------------------------------------------------------------------------------------------------------------------------

看到Graphics View Framework的时候,被窗口,视口,场景坐标系,对象坐标系,世界坐标系,逻辑坐标,物理坐标等等概念彻底搞懵了。到底他们之间是什么关系呢?是怎样映射的呢?到现在小狼还没有搞懂,不过经过不断试验,有了一点点自己的理解。

QPainter的各种draw方法是基于窗口坐标系的。

窗口坐标为逻辑坐标,是基于视口坐标系的。视口坐标为物理坐标,是基于绘图设备坐标系的。没有做过改动的情况下,他们是一样的,都是以绘图设备(paint device,qwidget,qpixmap等都为绘图设备)大小为大小,左上角为原点(0,0)。

窗口:

窗口代表视口的区域,他始终以视口坐标为最终目标进行映射(这句话的意思到下面讲视口的时候会再讲),他的大小和逻辑位置可以通过QPainter::setWindow()设置,但是无论大小和逻辑位置设置为什么数值,他始终代表着整个视口。

例如你有一个实际大小为200×200像素的窗口,那么原始状态之下窗口大小也是200×200,视口大小也是200×200,,在0,0位置画一个大小为100×100的矩形的时候,他会占视口左上角的4分之一。
painter.drawRect(0,0,100,100);

如果这时候我们通过QPainter::setWindow修改了窗口位置和大小,例如setWindow(-50,-50,100,100)

函数原型:
void QPainter::setWindow(int x, int y, int width, int height)

参数:
x:窗口左上角x坐标
y:窗口左上角y坐标
width:窗口长度(并非像素)
height:窗口高度(并非像素)

窗口代表的还是整个视口,但是映射的数值有所不同,这时候窗口的逻辑坐标(-50,-50)成为了视口坐标的(0,0),而窗口的逻辑大小成为了100×100的单位长度(这里用单位长度是因为窗口大小的长度并不固定,受视口大小影响),因为用100个单位长度代表原本物理大小的200像素,所以,每一个单位长度就是实际的2像素。因为QPainter是以窗口坐标为基础的,所以这时候画一个位置为(-50,-50),大小为 50,50的矩形。
painter.drawRect(-50,-50,50,50);
矩形还是占窗口的左上角的4分之一(下图左),而
painter.drawRect(0,0,50,50);
矩形占窗口右下角的4分之一。

而视口对应的则是物理坐标,没有改动的情况下,视口大小与绘图区大小一样,上面的例子中,视口的属性一直没有改变过,所以视口的左上角还是在绘图区的物理位置(0,0),在窗口坐标的(-50,-50)。大小为物理大小的

200×200像素,而为窗口坐标系下的100×100单位长度。

视口:

现在我们看看设置视口对绘图的影响,为了简单起见,先把上面的setWindow()一句注释掉,即现在窗口,视口是一样的。

现在来改变视口的属性,先用painter.setViewPort(0,0,100,100);
函数原型:
void QPainter::setViewport ( int x, int y, int width, int height )

参数:
x:设置视口左上角x坐标
y::设置视口左上角y坐标
width:设置视口长度(像素)
height:设置视口宽度(像素)

所以上面语句的作业就是把视口的的原点位置设置为绘图设备(这里是QDialog)的原点,大小改变为100,100。

那么现在是个什么情况呢?
现在我们把视口的坐标设置为绘图区的左上角(0,0)位置,大小设置为绘图区的一半,因为绘图区是(200×200),而我们把视口设置为(100×100)。即现在实际的绘图区为绘图设备的左上角的4分之一。

那么这时候我们再用
painter.drawRect(0,0,100,100);画一个矩形,实际显示是怎么样的呢?看下图:

绘制出来的是dialog的16分之一了,为什么会这样呢?

前面我们讲过窗口坐标始终以视口坐标为最终目标进行映射,而原来没有经过修改的窗口的属性为以左上角为原点,大小为200×200单位长度,我们修改视口大小为100×100像素后,窗口的200单位长度就映射到100像素的视口长度上,即每一单位长度为0.5像素,所以绘制出来的结果就是100×0.5=50像素,所以长和高都是dialog的4分之一,面积就是16分之一了

这时候如果我们拖动dialog边界改变dialog的大小会怎么样呢?小狼原本的想法是画出来的矩形应该还是占总大小的16分之一,实际上这是错的。
void Lang::paintEvent(QPaintEvent *)
{
QPainter painter(this);

    qDebug()<<"after drag:"<<endl;
qDebug()<<painter.viewport().width();
qDebug()<<painter.viewport().height();
painter.setViewport(0, 0, 100 ,100 );
//painter.setWindow(-50,-50,100,100);
painter.drawRect(0,0, 100, 100);
}

先通过painter.viewport().width()和heigth()获取当前实际视口大小(paintEvent之前,视口会被重置为绘图设备实际大小)。如下图,当我们把dialog拖动为400×400大小时,矩形框变得更小了。

其实这很简单。因为在paintEvent之前窗口值也会重置为dialog(绘图设备)大小,所以这时候窗口大小为400×400单位长度,而视口我们还是再设定为100×100像素,所以这时候窗口大小的一单位长度为实际的100/400=0.25像素,所以画一个100×100单位长度的矩形时,实际大小时25×25像素,所以变得更小

上图中我是用qq的截图功能进行测量,qq截图会给出当前截取图形的大小,正是25×25(圈的时候有所偏差).

最后再来看一个窗口和视口一起设置的例子.
void Lang::paintEvent(QPaintEvent *)
{
QPainter painter(this);

    qDebug()<<"after drag:"<<endl;
qDebug()<<painter.viewport().width();
qDebug()<<painter.viewport().height();
painter.setViewport(0, 0, 100 ,100 );
//painter.setWindow(-50,-50,100,100);
painter.drawRect(0,0, 100, 100);
}

这里设置窗口坐标(-50,-50)映射为视口的原点,把窗口100×100单位长度映射为视口的100×100像素大小
这时候窗口逻辑坐标-50,-50就是视口的坐标(0,0),也就是绘图设备的50,50坐标,所以窗口坐标(0,0)位置即绘图设备坐标的(100,100)
因为窗口坐标100单位长度映射到视口坐标的100像素,所以上图的painter.drawRect(0,0, 50, 50);一句绘制出了的结果就是在绘图设备的(100,100)位置绘制一个50×50像素的矩形。

总结:

要得到QPainter绘图的真正位置,要经过两步

第一步:
窗口坐标转换为视口坐标,转换公式为:
vp_width / win_width * (draw_x - win_x)
其中vp_width为视口长度,win_width为窗口长度,draw_x为实际要绘制的x左上坐标,win_x为窗口的x左上坐标,y坐标同理

窗口大小转换为视口大小,转换公式为:
draw_width * vp_width / win_width
draw_width为要绘制的窗口长度,vp_width为视口长度,win_width为窗口长度

height同理

第二步:

视口坐标转换为绘图设备坐标,这一步就简单的进行相加就好了
实际坐标x=上一步转换来的视口坐标+vp_x
vp_x为视口的左上x坐标,实际坐标y同理

转载地址:http://blog.csdn.net/syzobelix/article/details/9377863

qt坐标系统见解的更多相关文章

  1. 2.QT-窗口组件(QWidget),QT坐标系统,初探消息处理(信号与槽)

    本章主要内容如下: 1) 窗口组件(QWidget) 2) QT坐标系统 3) 消息处理(信号与槽) 窗口组件(QWidget) 介绍 Qt以组件对象的方式构建图形用户界面 Qt中没有父组件的顶级组件 ...

  2. qt坐标系统与布局的简单入门

     qt坐标系统 qt坐标系统比較简单 ); 上面的代码把button显示为父窗体的20,20处宽度为100,高度为100 接下去是布局 qt里面布局须要增加<QLayout.h>这个头 ...

  3. qt坐标系统

    #说明:坐标系统是由 QPainter控制的QPaintDevice是那些能够让 QPainter 进行绘制的“东西”(准确的术语叫做,二维空间)# 的抽象层(其子类有QWidget. QPixmap ...

  4. QT +坐标系统 + 自定义控件 + 对象树的验证(自动进行析构)_内存回收机制

    通过创建一个新的按钮类,来进行析构函数的验证,即对象树概念的验证.当程序结束的时候会自动的调用析构函数, 验证思路: 要验证按钮会不会自动的析构,(即在QPushButton类里面的析构函数添加qDe ...

  5. Qt中的坐标系统

    Qt使用统一的坐标系统来定位窗口部件的位置和大小. 以屏幕的左上角为原点即(0, 0)点,从左向右为x轴正向,从上向下为y轴正向,这整个屏幕的坐标系统就用来定位顶层窗口: 此外,窗口内部也有自己的坐标 ...

  6. 第7课 Qt中的坐标系统

    1. 坐标系统 (1)GUI操作系统都有特定的坐标系统 (2)图形界面程序在坐标系统中进行窗口和部件的定位 (3)定位类型 ①顶级窗口部件的定位 ②窗口内部件的定位 ③窗口部件的大小设置 (4)QWi ...

  7. QT-第一个程序 Hello QT , 以及QT creator介绍

    第一个程序 - Hello QT 首先写main.cpp: #include <QApplication> #include <QMainWindow> #include &l ...

  8. QT 二维图形 原理、发展及应用

    转载自 网易博客:sun的博客 http://zhouyang340.blog.163.com/blog/static/3024095920126710504178/ 2D绘图 Qt4中的2D绘图部分 ...

  9. QT入门学习笔记2:QT例程

    转至:http://blog.51cto.com/9291927/2138876 Qt开发学习教程 一.Qt开发基础学习教程 本部分博客主要根据狄泰学院唐老师的<QT实验分析教程>创作,同 ...

随机推荐

  1. 自己编写jQuery插件之Tab切换

    自己编写jQuery插件之 Tabs切换 jquery ui 带有Tabs切换插件,但其css样式太难维护,引用的东西太多,因此就自己写了个. 起初我Html代码架子是这样的: <div cla ...

  2. 配置文件的属性ENC加密

    转载:https://www.cnblogs.com/zqyx/p/9687136.html 在micro service体系中,有了config server,我们可以把配置存放在git.svn.数 ...

  3. Oracle 物理结构(六) 文件-数据文件

    Oracle 物理结构(六) 文件-数据文件

  4. 为什么margin:0 auto不能用于inline-block元素

    前言:今天一个实习生问我,为什么他对图片使用了margin:0 auto,但图片却没有居中,我让他换成对父元素使用text-align:center即可.为什么margin:0 auto对图片不起作用 ...

  5. DP(第二版)

    第一版请见:直通 话不多说,直接上题 1.P1040 加分二叉树 直通 思路: 已知中序遍历,相当于一段区间了,所以我们枚举一个k,如果以k为根节点,能够将分数更新,那么这段区间的根节点就置为k,最后 ...

  6. Machine Schedule为什么UVA过了POJ过不了

    UVA1194 POJ1325 POJ要多判一个非零!!! #include<cstdio> #include<vector> #include<cstring> ...

  7. 2019.7.9 校内测试 T2 极值问题

    这一次是交流测试?边交流边测试(滑稽 极值问题 乍一看这是一道数学题,因为1e9的数据让我暴力的心退却. 数学又不好,不会化简式子嘞,咋办? 不怕,咱会打表找规律.(考场上真的是打表找出了规律,打表打 ...

  8. NTP 协议介绍

    NTP协议 NTP(Network Time Protocol,网络时间协议)是由RFC 1305定义的时间同步协议,用来在分布式时间服务器和客户端之间进行时间同步.NTP基于UDP报文进行传输,使用 ...

  9. Babel7知识梳理

    Babel7 知识梳理 对 Babel 的配置项的作用不那么了解,是否会影响日常开发呢?老实说,大多情况下没有特别大的影响(毕竟有搜索引擎). 不过呢,还是想更进一步了解下,于是最近认真阅读了 Bab ...

  10. 跨域请求错误: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource

    今天在学习Angular 的HttpInterceptor 拦截器时,发现添加了新的headers键值之后总是报跨域错误.后台使用的是asp.net core. 检查发现,在添加了新的header之后 ...