大纲:
    基本变换
        介绍和常用API
    窗口-视口转换
        窗口
        视口
        让窗口和视口维持相同宽高比来防止变形
 
基本变换
默认的,QPainter在相关设备的坐标系统上进行操作,但是它也完全支持仿射(affine)坐标变换(仿射变换的具体概念请查看其他资料)。
 
绘图时可以使用常用API:
QPainter::scale()函数缩放坐标系统;
QPainter::rotate()函数顺时针旋转坐标系统;
QPainter::translate()函数平移坐标系统;
QPainter::shear()围绕原点来扭曲坐标系统;
QPainter::save()用来保存QPainter的变换矩阵;
QPainter::restore()用来恢复QPainter的变换矩阵;
 
例如:
    //平移坐标系统,也就是说以(200,150)作为新的原点(0,0)
    QPainter::translate(200, 150); //水平移到200, 垂直移动150
     
    //旋转坐标系统
    //rotate()函数会以原点为中心进行旋转,参数为旋转的角度,正数为顺时针旋转,负数为逆时针旋转
    QPainter::rotate(90);
 
窗口-视口转换
使用QPainter进行绘制时,会使用逻辑坐标进行绘制,然后再转换为绘图设备的物理坐标。
逻辑坐标到物理坐标的映射主要由以下的函数来处理:
QPainter的worldTransform()函数;
QPainter的viewport()函数;
QPainter的window()函数
其中,视口(viewport)表示物理坐标下指定的一个任意矩形,而窗口(window,与以前讲的窗口部件的概念不同)表示逻辑坐标下的相同矩形。默认的,逻辑坐标和物理坐标是重合的,它们都相当于绘图设备上的矩形。
 
1. 窗口(逻辑区域)
窗口代表要逻辑处理的区域,它始终以视口(物理)坐标为最终目标进行映射,他的大小和逻辑位置可以通过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)
设置完后,窗口代表的还是整个视口(物理),但是映射的数值有所不同:
此时窗口的逻辑坐标(-50,-50)对应视口(物理)坐标的(0,0)。
而窗口的逻辑大小成为了100×100的单位长度,也就是用100个单位长度代表原本物理大小的200像素,所以每一个单位长度就是实际的2像素。
 
因为QPainter是以窗口(逻辑)坐标为基础的,所以这时候画一个位置为(-50,-50),大小为 50,50的矩形。
painter.drawRect(-50,-50,50,50);还是和以前画的是一样的的效果。
 
也就是说,我们将窗口(逻辑)宽 100px 映射成视口(物理)宽 200px,窗口高 100px 映射成物理高 200px,逻辑-50,-50映射成物理的0,0。
 
 
2. 视口(物理区域)
现在来改变视口的属性,先用painter.setViewPort(0,0,100,100);
上面语句的作用就是把把视口的坐标设置为绘图区的左上角(0,0)位置,大小设置为绘图区的一半,因为绘图区是(200×200),而我们把视口设置为(100×100)。
 
即现在实际的绘图区为绘图设备的左上角的4分之一。
也就是说,我们将视口(物理)宽 100px 映射成窗口(逻辑)宽 200px,视口高 100px 映射成窗口高 200px。
这时候我们再用
painter.drawRect(0,0,100,100);
画一个矩形,实际显示是怎么样的呢?看下图:
绘制出来的是dialog的16分之一了,为什么会这样呢?
 
前面我们讲过窗口坐标始终以视口(逻辑)坐标为最终目标进行映射,而原来没有经过修改的窗口的属性为以左上角为原点,大小为200×200单位长度,我们修改视口大小为100×100像素后,窗口的200单位长度就映射到100像素的视口长度上,即每一单位长度为0.5像素,所以绘制出来的结果就是100×0.5=50像素,所以长和高都是dialog的4分之一,面积就是16分之一了。
 
3. 让视口和窗口维持相同的宽高比来防止变形
int side = qMin(width(), height()); //取长度和宽度的最小值
int x = (width() - side/2);
int y = (height() - side/2);
painter.setViewport(x,y,side,side); //物理的(x,y)映射成逻辑的(0,0);物理的宽side,映射成逻辑的width()......
 
参考:
 
本篇源代码
 
 

[Qt2D绘图]-03坐标系统之坐标变换的更多相关文章

  1. [Qt2D绘图]-02坐标系统&&抗锯齿渲染

    本节的内容可以在帮助中通过Coordinate System关键字查看. 或者入门可以看<Qt Creator 快速入门>这本书.强烈推荐入门使用.下面的内容为本书的阅读笔记,喜欢的可以买 ...

  2. 【转 | 侵删】2D 绘图技术中的坐标系统与坐标变换

    本文介绍在 2D 绘图技术中的坐标系统和坐标变换的相关知识.同时介绍 Kity 在这方面提供的 API .希望这些知识对于需要进行图形应用开发的同学会有所帮助. 锤子的故事 很久以前,有一个画家,他很 ...

  3. [Qt2D绘图]-06QPainter的复合模式&&双缓冲绘图&&绘图中的其他问题

    本篇读书笔记主要记录QPainter的复合模式&&双缓冲绘图&&绘图中的其他问题   大纲:     复合模式     双缓冲绘图     绘图中的其他问题       ...

  4. [Qt2D绘图]-04绘制文字&&绘制路径

    注:学习自<Qt Creator 快速入门>第三版.   文档中的示例参考 Qt Example推荐:Painter Paths Example和Vector Deformation   ...

  5. Delphi下OpenGL2d绘图(03)-画线

    一.前言 画线与画点基本上代码是相同.区别在于glBegin()的参数.绘制的框架代码可以使用 Delphi下OpenGL2d绘图(01)-初始化 中的代码.修改的部份为 Draw 函数的内容. 二. ...

  6. [Qt2D绘图]-05绘图设备-QPixmap&&QBitmap&&QImage&&QPicture

    这篇笔记记录的是QPainterDevice(绘图设备,可以理解为一个画板) 大纲:     绘图设备相关的类:QPixmap QBitmap QImage QPicture     QPixmap ...

  7. [Qt2D绘图]-01Qt2D绘图基本绘制和填充

    Qt的文档位置为 Paint System   大纲:     简介     先看一个小例子     基本的绘制和填充         使用画笔(Qpen)         使用画刷(QBrush) ...

  8. qt 坐标变换

    原文链接:Qt学习之路(28): 坐标变换   同很多坐标系统一样,QPainter的默认坐标的原点(0, 0)位于屏幕的左上角,X轴正方向是水平向右,Y轴正方向是竖直向下.在这个坐标系统中,每个像素 ...

  9. Qt学习之路(28): 坐标变换

    经过前面的章节,我们已经能够画出一些东西来,主要就是使用QPainter的相关函数.今天,我们要看的是QPainter的坐标系统.   同很多坐标系统一样,QPainter的默认坐标的原点(0, 0) ...

随机推荐

  1. 技术周刊 · Lighthouse 测试报告生成

    登高远眺 天高地迥,觉宇宙之无穷 基础技术 Lighthouse 测试内幕 文章分享了网易云音乐前端性能监控平台使用 Lighthouse 的实践经验,介绍了 Lighthouse 的测试流程.内部模 ...

  2. 解决mysql插入数据l出现"the table is full"的问题

    需要修改Mysql的配置文件my.ini,在[mysqld]下添加/修改两行:tmp_table_size = 256Mmax_heap_table_size = 256M

  3. C/C++以及Linux文件操作备忘录

    目录 C文件操作 文件开关 文件读写 C++文件操作 Linux文件操作 打开 C文件操作 #include<stdio.h> stdin, stdout, stderr 文件开关 /* ...

  4. 多语言工作者の十日冲刺<4/10>

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 团队进行Alpha冲刺--第四天(05.03) 作业正文 ...

  5. 在运行时生成C# .NET类

    ​本文译自​:​Generating C# .NET Classes at Runtime 作者:WedPort 在我的C#职业生涯中,有几次我不得不在运行时生成新的类型.希望把它写下来能帮助有相同应 ...

  6. Matlab矩阵间快速赋值方法

    目前还没见到网上用过这个简单的方式 A= [1 2 3; 4 5 6; 7 8 9] B = zeros(5,5) B(1:3, 2:4) = A     %将A赋值到B的第1行到3行,第2列岛4列, ...

  7. LQR要点

    新的“A”变成着了这样:Ac = A - KB 基于对象:状态空间形式的系统 能量函数J:也称之为目标函数 Q:半正定矩阵,对角阵(允许对角元素出现0) R:正定矩阵,QR其实就是权重 下面这段话可能 ...

  8. Python实用笔记 (9)高级特性——列表生成式

    列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式. 举个例子,要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, ...

  9. 如何理解nginx反向代理,其实叫逆向代理更容易让我理解

    接触nginx后,以我的语文水平,一直无法理解它神奇的名字:反向代理 怎么就反向了?反哪里去了 (以下部分图片.内容来自网络整理) 1.先理解正向代理 正向代理( Forward Proxy ): 客 ...

  10. Python3笔记017 - 4.2 列表

    第4章 序列的应用 python的数据类型分为:空类型.布尔类型.数字类型.字节类型.字符串类型.元组类型.列表类型.字典类型.集合类型 在python中序列是一块用于存放多个值的连续内存空间. py ...