大纲:
    基本变换
        介绍和常用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()......
 
参考:
 
本篇源代码
 
 

最新文章

  1. Linux命令:简单函数调用
  2. jquery获取复选框(checkbox)的选中值(一组和单个)
  3. HTML的标签-W3School读后总结
  4. IE兼容性问题解决方案3--css中的overflow
  5. [译]36 Days of Web Testing(二)
  6. python中eval, exec, execfile,和compile [转载]
  7. HTML学习(六)图像
  8. docker - 容器里安装mysql
  9. My "Top 5 R Functions"(转)
  10. C# 实现AOP 的几种常见方式
  11. AngularJS学习篇(十五)
  12. Android4.0 声卡配置-高通msm8916移植
  13. Java数据库基础(JDBC)
  14. [USACO 07NOV]Cow Relays
  15. 查看SQL Server服务运行帐户和SQL Server的所有注册表项
  16. print number
  17. docker往阿里云推镜像和打包镜像
  18. go 调用windows dll 的三种方法
  19. html 字符串 生成 pdf 完美解决中文不显示
  20. DSO windowed optimization 代码 (3)

热门文章

  1. 如何用Python从海量文本抽取主题?
  2. WeChair项目Beta冲刺(2/10)
  3. Redis设置并查看最大连接数
  4. zabbix4.4安装
  5. 深入理解JVM(③)虚拟机的类加载器(双亲委派模型)
  6. 学习Java的Day04
  7. Idea+springboot入坑之路
  8. 08 . Kubernetes之 ingress及Ingress Controller
  9. Springboot 2.X的RequestMapping 的映射路径怎么看不到了?
  10. js中取el表达式问题