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

本文详细介绍了Qt中的坐标系统,包括逻辑坐标、物理坐标和窗口视口坐标的概念,以及如何通过平移、旋转、缩放和扭曲进行坐标变换。此外,还解释了QRect和QRectF的区别,并展示了如何避免坐标计算中的问题。通过示例代码,阐述了setWindow和setViewport方法如何影响绘制区域,强调了在Qt图形绘制中的坐标映射和转换的重要性。
摘要由CSDN通过智能技术生成


坐标系统

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()

代码

http://blog.csdn.net/yulinxx/article/details/43260203 ------------------------------------------ C++ 国际化!!!!! 创建一个空白的Qt工程 添加一个main.cpp #include #include #include #include int main(int argc, char *argv[]) { QApplication a(argc, argv) QWidget* pWnd = new QWidget(); QPushButton* pBtn = new QPushButton(QPushButton::tr("Test Translate")) QVBoxLayout* pVlayout = new QVBoxLayout(); pVlayout->addWidget(pBtn) pWnd->setLayout(pVlayout); pWnd->show(); return a.exec(); } 即可运行起来。。。。 此工程中,只有按钮上有文字。。。运行如下图示: 在工程中加入: TRANSLATIONS += testTrans_en.ts (ts文字名可随意取) 然后执行: Tools -> External -> Linguist -> Update Translations(lupdate) 提示完成: /usr/local/Qt5.4.0/5.4/gcc_64/bin/lupdate" finished 在工程中,可以发现多了一个 testTrans_en.ts 文件,此文件可用文本编辑器打开进行查看,如: QPushButton Test Translate 此步骤是将工程中的文字(加tr等包含的文字)进行提取到ts文件中 接下来,在终端运行 x@x:~$ linguist 打开 Qt Linguist 翻译工具,对文字进行逐个翻译并保存 在工程中再执行: Tools -> External -> Linguist -> Release Translations(lrelease) 结果提示:/usr/local/Qt5.4.0/5.4/gcc_64/bin/lrelease" finished 在工程中,可以发现多了一个 testTrans_en.qm文件,此文件为二进制格式文件,即我们最终使用的翻译文件 然后添加Qt资源,将testTrans_en.qm添加进来 修改main.cpp文件,将翻译文件添加进来,最终执行 #include #include #include #include int main(int argc, char *argv[]) { QApplication a(argc, argv); QTranslator qtTranslator; qtTranslator.load(":/translate/testTrans_en.qm") a.installTranslator(&qtTranslator); QWidget* pWnd = new QWidget(); QPushButton* pBtn = new QPushButton(QPushButton::tr("Test Translate")) QVBoxLayout* pVlayout = new QVBoxLayout(); pVlayout->addWidget(pBtn) pWnd->setLayout(pVlayout); pWnd->show() return a.exec() } 最终执行结果:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二进制怪兽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值