#说明:坐标系统是由 QPainter控制的QPaintDevice是那些能够让 QPainter 进行绘制的“东西”(准确的术语叫做,二维空间)
# 的抽象层(其子类有QWidget、 QPixmap、 QPicture、 QImage 和 QPrinter 等); QPaintEngine 提供供 QPainter#,使用的用于在不同设备上绘制的统一的接口。
#概念:坐标系统,也就是 QPaintDevice 上面的坐标。默认坐标系统位于设备的左上角,也就是坐标原点 (0, 0)。x 轴方向向右;y 轴方
# 向向下。在基于像素的设备上(比如显示器),坐标的默认单位是像素,在打印机上则是点(1/72 英寸)。
"""
将 QPainter 的逻辑坐标与 QPaintDevice 的物理坐标进行映射的工作,是由 QPainter 的
变换矩阵(transformation matrix)、视口(viewport)和窗口(window)完成的。如果你不
理解这些术语,可以简单了解下有关图形学的内容。实际上,对图形的操作,底层的数学都
是进行的矩阵变换、相乘等运算。
在 Qt 的坐标系统中,每个像素占据 1×1 的空间。你可以把它想象成一张方格纸,每个小
格都是 1 个像素。方格的焦点定义了坐标,也就是说,像素 (x, y) 的中心位置其实是在 (x +
0.5, y + 0.5) 的位置上。这个坐标系统实际上是一个“半像素坐标系”。我们可以通过下面的
示意图来理解这种坐标系
"""

如图:

我们使用一个像素的画笔进行绘制, 可以看到,每一个绘制像素都是以坐标点为中心的矩形。
注意,这是坐标的逻辑表示,实际绘制则与此不同。因为在实际设备上,像素是最小单位,

在实际绘制时,Qt 的定义是,绘制
点所在像素是逻辑定义点的右下方的像素。

如图:绘制矩形左上角  (1, 2)  时,实际绘制的像素是在右下方.

当绘制大于 1 个像素时,情况比较复杂:如果绘制像素是偶数,则实际绘制会包裹住逻辑坐
标值;如果是奇数,则是包裹住逻辑坐标值,再加上右下角一个像素的偏移

如图:如果实际绘制是偶数像素,则会将逻辑坐标值夹在相等的两部分像素之间;如果是奇数,则会在右下方多出一个像素.

QRect::right()和 QRect::bottom()的返回值并不是矩形右下角点的真实坐标值.

QRect::right()返回的是  left() + width() –  1;QRect::bottom()则返回  top() + height()  –  1

QRectF 使用浮点值

这个类的两个函数 QRectF::right()和 QRectF::bottom()是正确的。如果你不得不使
用 QRect,那么可以利用 x() + width() 和 y() + height() 来替代 right() 和 bottom() 函数。

对于反走样,实际绘制会包裹住逻辑坐标值:

如图:

坐标变换:QPainter::save()和 QPainter::restore()当我临时绘制某

些图像时,就可能想这么做。当然,我们有最原始的办法:将可能改变的状态,比如画笔颜
色、粗细等,在临时绘制结束之后再全部恢复。对此, QPainter 提供了内置的函数: save()
和 restore()。save()就是保存下当前状态;restore()则恢复上一次保存的结果。这两个函数
必须成对出现: QPainter 使用栈来保存数据,每一次 save(),将当前状态压入栈顶, restore()
则弹出栈顶进行恢复。

from PyQt4.QtGui import  *

from PyQt4.Qt import *

from PyQt4 import QtGui, QtCore

from PyQt4.QtCore import *

import sys

class Painterd(QWidget):

def __init__(self):

super(Painterd,self).__init__()

self.resize(400,300)

self.setWindowTitle('paint')

def paintEvent(self, e):

paint=QPainter(self)

paint.fillRect(10,10,50,100,Qt.red)#在  (10, 10)  点绘制一个红色的  50×100  矩形

paint.save()#保存当前状态

paint.translate(100,0)#向右平移100像素

paint.fillRect(10,10,50,100,Qt.yellow)

paint.restore()#恢复先前状态

paint.save()

paint.translate(300,0)

paint.rotate(30)#顺时针旋转30度

paint.fillRect(10,10,50,100,Qt.green)

paint.restore()

paint.save()

paint.translate(400,0)

paint.scale(2,3)#横坐标单位放大2倍,纵坐标放大3倍

paint.fillRect(10,10,50,100,Qt.blue)

paint.restore()

paint.save()

paint.translate(600,0)

paint.shear(0,1)#横坐标单位不变,纵坐标扭曲1倍

paint.fillRect(10,10,50,100,Qt.cyan)

paint.restore()

#平移  translate,旋转  rotate,缩放  scale  和扭曲  shear

def main():

app = QtGui.QApplication(sys.argv)

ex =Painterd()

ex.show()

sys.exit(app.exec_())

if __name__ == '__main__':

main()

如图:

#其他说明:Qt的坐标分为逻辑坐标和物理坐标,QPainter 的都是逻辑坐标绘制底层QPaintDevice 的坐标。单单只有逻辑坐标,Qt  使用  viewport- window  机制将我们提供的逻辑

# 坐标转换成绘制设备使用的物理坐标方法是,

# 在逻辑坐标和物理坐标之间提供一层“窗口”坐标。视口是由任意矩形指定的物理坐标;窗口则是该矩形的逻辑坐标表示。

# 默认情况下,物理坐标和逻辑坐标是一致的,都等于设备矩形。

#视口坐标(也就是物理坐标)和窗口坐标是一个简单的线性变换。比如一个  400×400  的窗口:

def paintEvent(self, e):

paint=QPainter(self)

paint.setWindow(0,0,200,200)

paint.fillRect(0,0,200,200,Qt.red)

如图:

将窗口矩形设置为左上角坐标为 (0, 0),长和宽都是 200px。此时,坐标原点不变,还
是左上角,但是,对于原来的 (400, 400) 点,新的窗口坐标是 (200, 200)。我们可以理解成,
逻辑坐标被“重新分配”。这有点类似于 translate(),但是,translate()函数只是简单地将坐
标原点重新设置,而 setWindow()则是将整个坐标系进行了修改。这段代码的运行结果是
将整个窗口进行了填充。

def paintEvent(self, e):

paint=QPainter(self)

paint.translate(200,200)

#坐标原点设置到 (200, 200) 处,横坐标范围是 [-200, 200],纵坐标范围是 [ -200, 200]。

paint.setWindow(-160,-320,320,640)

#坐标原点也是在窗口正中心,但是,我们将物理宽 400px 映射成窗口宽 320px,物理高 400px 映射成窗口高 640px ,此时,横坐标范围是 [ -160, 160],纵坐标范围

是 [ -320, 320]

如图:

#设原来有个点坐标是 (64 , 60),那么新的窗口坐标下对应的坐标应该是 ((-160 + 64 * 320 / 400), (-320 + 60 * 640 / 400)) = (-108.8, -224)。

逻辑坐标、窗口坐标和物理坐标之间的关系:

def paintEvent(self, e):

paint=QPainter(self)

paint.setViewport(0, 0, 200, 200)#viewport  代表物理坐标

"""

默认的逻辑坐标范围是左上角坐标为  (0, 0) ,

长宽都是  400px  的矩形。当我们将物理坐标修改为左上角位于  (0, 0),长高都是  200px  的

矩形时,窗口坐标范围不变,也就是说,我们将物理宽  200px  映射成窗口宽  400px,物理

高  200px  映射成窗口高  400px,所以,原始点  (200, 200)  的坐标变成了  ((0 + 200 * 200 /

400), (0 + 200 * 200 / 400)) = (100, 100)。

"""

paint.fillRect(0, 0, 200, 200, Qt.red)

如图:

#其他说明:传给 QPainter 的是逻辑坐标(也称为世界坐标),逻辑坐标可以通过变换矩阵转换成

窗口坐标,窗口坐标通过 window-viewport 转换成物理坐标(也就是设备坐标)

#更多信息请看:http://www.linuxidc.com/Linux/2011-07/39246.htm

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 +坐标系统 + 自定义控件 + 对象树的验证(自动进行析构)_内存回收机制

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

  4. qt坐标系统见解

    窗口坐标为逻辑坐标,是基于视口坐标系的. 视口坐标为物理坐标,是基于绘图设备坐标系的 窗口坐标始终以视口坐标为最终目标进行映射: QPainter::setWindow 修改了窗口位置和大小(左上角重 ...

  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. 【Android 应用开发】 ActionBar 样式详解 -- 样式 主题 简介 Actionbar 的 icon logo 标题 菜单样式修改

    作者 : 万境绝尘 (octopus_truth@163.com) 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/3926916 ...

  2. 深入浅出理解iOS经常使用的正則表達式—基础篇[Foundation]

    參考资料:cocoachina的zys475481075的文章 几个单词 Regular ['regjʊlə]adj. 定期的:有规律的 Expression[ɪk'spreʃ(ə)n; ek-] n ...

  3. Oracle CheckPoint进程

    在实例经过分配内存结构,加载控制文件后,然后要打开数据库的时候,需要做到控制文件,数据文件,联机重做日志保持相互状态一致性,数据库才可以打开.当数据库发生实例不正常关闭时(比如系统掉电或者Shutdo ...

  4. js调用百度地图搜索功能

    引用百度jsApi <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&a ...

  5. 安卓状态栏通知Status Bar Notification

    安卓系统通知用户三种方式: 1.Toast Notification 2.Dialog Notification 3.Status Bar Notification Status Bar Notifi ...

  6. C#图像处理(2):给图片加白边

    C#图片处理给图片添加白边: /// <summary> /// 在图片上方加入白边 /// </summary> /// <param name="Img&q ...

  7. 系统提供的UIImagePickerController

    1.从系统相册中读取 /* 判断选择的读取类型是否支持 UIImagePickerControllerSourceTypePhotoLibrary,普通相册 UIImagePickerControll ...

  8. 如何在Visual studio中修改所使用C#语言的版本

    有时候,我们需要在Visual studio里修改当前使用的C#语言的版本,具体修改方法如下:在solution explorer中右键工程->选择属性->切换到Build页->点击 ...

  9. 基于'sessionStorage'与'userData'的类session存储

    Storage.js: 注意:此版本实现的存储在符合Web存储标准(ie8及ie8以上的版本与其他主流浏览器)的情况下与session的周期一致,但在页面不关闭的情况下没有过期时间,ie7及以下版本则 ...

  10. OpenGL ES 2.0 绘制方式

    OpenGL ES 中支持的绘制方式大致分3类,包括点.线段.三角形,每类中包括一种或多种具体的绘制方式. GL_POINTS 传入渲染管线的一系列顶点单独进行绘制. GL_LINES   传入渲染管 ...