[学习][笔记] qt5 从入门到入坟:<10>坐标系统

简介: [学习][笔记] qt5 从入门到入坟:<10>坐标系统

坐标系统

Qt 学习之路 2(28):坐标系统

Qt中坐标:窗口坐标,视口坐标

所谓坐标系统,也就是QPaintDevice上面的坐标。默认坐标系统位于设备的左上角,也就是坐标原点 (0, 0)。x 轴方向向右;y 轴方向向下。

将QPainter的逻辑坐标与QPaintDevice的物理坐标进行映射的工作,是由QPainter的变换矩阵(transformation matrix)、视口(viewport)和窗口(window)完成的。

在 Qt 的坐标系统中,每个像素占据 1×1 的空间。你可以把它想象成一张方格纸,每个小格都是1个像素。方格的焦点定义了坐标,也就是说,像素 (x, y) 的中心位置其实是在 (x + 0.5, y + 0.5) 的位置上。这个坐标系统实际上是一个“半像素坐标系”。我们可以通过下面的示意图来理解这种坐标系:

绘制矩形

当我们绘制矩形左上角 (1, 2) 时,实际绘制的像素是在右下方。

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

从上图可以看出,

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

Qt 的这种处理,带来的一个问题是,我们可能获取不到真实的坐标值。由于历史原因,QRect::right()和QRect::bottom()的返回值并不是矩形右下角点的真实坐标值:QRect::right()返回的是

left() + width() – 1;QRect::bottom()则返回 top() + height() –1,上图的绿色点指出了这两个函数的返回点的坐标。

为避免这个问题,我们建议是使用QRectF。

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

坐标变换

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

Qt 提供了四种坐标变换:平移 translate,旋转 rotate,缩放 scale,扭曲 shear

平移 translate

旋转 rotate

缩放 scale

扭曲 shear

视口坐标和窗口坐标

Qt 的坐标分为逻辑坐标和物理坐标。

在我们绘制时,提供给QPainter的都是逻辑坐标。

之前我们看到的坐标变换,也是针对逻辑坐标的。

所谓物理坐标,就是绘制底层QPaintDevice的坐标。

单单只有逻辑坐标,我们是不能在设备上进行绘制的。要想在设备上绘制,必须提供设备认识的物理坐标。

Qt 使用 viewport-window 机制将我们提供的逻辑坐标转换成绘制设备使用的物理坐标,

方法是,在逻辑坐标和物理坐标之间提供一层“窗口”坐标。

视口是由任意矩形指定的物理坐标;

窗口则是该矩形的逻辑坐标表示。

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

窗口坐标(逻辑坐标)

PaintedWidget::PaintedWidget(QWidget *parent) :
    QWidget(parent)
{
    resize(400, 400);//设置了窗口的大小和标题
    setWindowTitle(tr("Paint Demo"));
}
void PaintDemo::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setWindow(0, 0, 200, 200);
    painter.fillRect(0, 0, 200, 200, Qt::red);
}

如代码 没setWindows时 红色矩形为窗体四分之一 ,设置之后,红色矩形为整个窗体。 为什么呢?

窗口为逻辑坐标,将400400的窗体映射为了200200,原本对应1像素的单位变成了对应2像素的单位,

20012001=200200 原本的四分之一

20022002 = 400400 正好是物理像素大小 fillRect以新单位为单位

400*400即铺满大小

补充:

translate()函数只是简单地将坐标原点重新设置.

setWindow()则是将整个坐标系进行了修改。这段代码的运行结果是将整个窗口进行了填充。

painter.translate(200, 200);

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

painter.setWindow(-160, -320, 320, 640);

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

视口(物理坐标)

PaintedWidget::PaintedWidget(QWidget *parent) :
    QWidget(parent)
{
    resize(400, 400);//设置了窗口的大小和标题
    setWindowTitle(tr("Paint Demo"));
}
void PaintDemo::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
//    painter.setWindow(0, 0, 400, 400);//等同于默认
    painter.setViewport(0, 0, 200, 200);
    painter.fillRect(0, 0, 200, 200, Qt::red);
}

如代码所示,没setViewPort之前 红色矩形 为窗体四分之一 setViewPort之后 红色矩形为窗体十六分之一

为什么呢?

视口为物理坐标,将400400物理像素 压缩成了200200物理像素 新单位为原本0.5像素 2000.52000.5 =
100
100 像素 对应400*400的正好为十六分之一

总结

(窗口坐标)逻辑坐标 -》 窗体坐标 -》 (视口坐标)物理坐标

即setWindow():resize(400*400):setViewPort()

代码

相关文章
|
2月前
|
存储 Windows
(13) Qt事件系统(two)
文章详细介绍了Qt事件系统,包括事件分发、自定义事件、事件传播机制、事件过滤以及事件与信号的区别。
106 3
(13) Qt事件系统(two)
|
2月前
|
存储 SQL 数据库连接
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
127 13
|
2月前
|
数据可视化 编译器 API
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
141 2
|
2月前
|
存储 SQL 数据库连接
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
100 2
|
2月前
|
编解码 程序员
(12)Qt事件系统(one)
本文详细介绍了Qt事件系统,包括各种系统事件、鼠标事件、键盘事件、定时器等的处理方法和示例代码。
94 0
(12)Qt事件系统(one)
|
3月前
|
定位技术 Go 开发工具
dynamic-situational-awareness-qt学习记录
本文是作者yantuguiguziPGJ关于dynamic-situational-awareness-qt学习记录的分享,介绍了在Qt学习过程中发现的qml资源丰富的代码仓库,并提供了资源路径和相关的安装、配置步骤,涉及的内容有数字地球、GIS纹理等,同时提供了相关链接和git命令来克隆代码仓库和ArcGIS Runtime SDK for Qt的安装说明。
|
2月前
|
编译器 API C语言
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
170 0
|
4月前
|
存储 C++
【C++】C++ 基于QT实现散列表学生管理系统(源码+数据+课程论文)【独一无二】
【C++】C++ 基于QT实现散列表学生管理系统(源码+数据+课程论文)【独一无二】
105 1
【C++】C++ 基于QT实现散列表学生管理系统(源码+数据+课程论文)【独一无二】
|
4月前
|
API
Qt绘图之Paint系统
Qt绘图之Paint系统
68 2
|
4月前
|
开发者
【Qt 学习笔记】Qt系统相关 | Qt事件 | 事件的介绍及基本概念
【Qt 学习笔记】Qt系统相关 | Qt事件 | 事件的介绍及基本概念
237 4