坐标系
QPainter 坐标系由QPainter 类控制。该类与QPaintDevice 和QPaintEngine 类共同构成Qt绘图系统Arthur的基础。QPainter 用于执行绘图操作,QPaintDevice 是对二维空间的抽象表示(可通过QPainter 在该空间上进行绘制),而QPaintEngine 则提供了绘图器用于在不同类型设备上绘图的接口。
QPaintDevice 类是可绘制对象的基类:其绘图功能被QWidget 、QImage 、QPixmap 、QPicture 和QOpenGLPaintDevice 类所继承。绘图设备的默认坐标系原点位于左上角。x值向右递增,y值向下递增。在基于像素的设备上,默认单位为 1 像素;在打印机上,默认单位为 1 点(1/72 英寸)。
逻辑坐标QPainter 与物理坐标QPaintDevice 之间的映射由QPainter 的变换矩阵、视口和“窗口”处理。默认情况下,逻辑坐标系与物理坐标系重合。QPainter 还支持坐标变换(例如旋转和缩放)。
渲染
逻辑表示
图形基元的大小(宽度和高度)始终与其数学模型相对应,不考虑渲染时所用画笔的宽度:
| QRect(QPoint(1, 2),QPoint(7, 6)) | QLine(QPoint(2, 7),QPoint(6, 1)) |
| QLine(2, 7, 6, 1) | |
| QRect(QPoint(1, 2),QSize(6, 4)) | |
| QRect(1, 2, 6, 4) |
抗锯齿绘制
在绘制时,像素渲染由QPainter::Antialiasing 渲染提示控制。
RenderHint 枚举用于向QPainter 指定标志,但特定引擎可能遵循也可能不遵循这些标志。QPainter::Antialiasing 值表示引擎应在可能的情况下对基元边缘进行抗锯齿处理,即通过使用不同的颜色强度来平滑边缘。
但默认情况下,绘图笔会产生锯齿,且适用其他规则:使用宽度为 1 像素的画笔渲染时,像素将被渲染在数学定义点的右侧和下方。例如:
使用像素数为偶数的画笔渲染时,像素将围绕数学定义的点对称渲染;而使用像素数为奇数的画笔渲染时,多出的像素将像一像素宽的情况一样,渲染在数学定义点的右侧和下方。具体示例请参见下方的QRectF 图表。
| QRectF | |
|---|---|
![]() | ![]() |
| 逻辑表示 | 一像素宽的笔 |
![]() | ![]() |
| 两像素宽的画笔 | 3像素宽的画笔 |
请注意,由于历史原因,QRect::right() 和QRect::bottom() 函数的返回值与矩形真正的右下角位置存在偏差。
QRect right() 函数返回 () + () - 1,而 () 函数返回 () + () - 1。图中的右下角绿色点显示了这些函数的返回坐标。left width bottom top height
我们建议您直接使用QRectF :QRectF 类使用浮点坐标在平面上定义矩形以确保精度(QRect 使用整数坐标),且QRectF::right() 和QRectF::bottom() 函数确实返回真正的右下角坐标。
或者,使用QRect ,依次调用x() +width() 和y() +height() 来确定右下角位置,并避免使用right() 和bottom() 函数。
抗锯齿绘制
若将QPainter 的anti-aliasing 渲染提示设置为 ,像素将在数学定义点的两侧对称渲染:
变换
默认情况下,QPainter 在关联设备的自有坐标系中运行,但它也完全支持仿射坐标变换。
您可以使用QPainter::scale() 函数按给定的偏移量缩放坐标系,使用QPainter::rotate() 函数将其顺时针旋转,并使用QPainter::translate() 函数对其进行平移(即向坐标点添加给定的偏移量)。
您还可以使用QPainter::shear() 函数围绕原点对坐标系进行扭转变换。所有变换操作都是基于QPainter 的变换矩阵进行的,您可以通过QPainter::worldTransform() 函数获取该矩阵。矩阵将平面上的一个点变换为另一个点。
如果您需要反复执行相同的变换,还可以使用QTransform 对象以及QPainter::worldTransform()和QPainter::setWorldTransform()函数。您可以随时通过调用QPainter::save()函数来保存QPainter 的变换矩阵,该函数会将矩阵保存在内部栈中。QPainter::restore()函数可将其弹出。
经常需要使用变换矩阵的情况之一,是在各种绘图设备上复用相同的绘图代码。如果不进行变换,绘图结果将严格受限于绘图设备的分辨率。打印机具有较高的分辨率(例如每英寸600点),而屏幕的分辨率通常在每英寸72到100点之间。
| 模拟时钟示例 | |
|---|---|
![]() | “模拟时钟”示例演示了如何利用QPainter 的变换矩阵绘制自定义控件的内容。 建议您在继续阅读之前先编译并运行此示例。特别是,请尝试将窗口调整为不同的大小。 |
我们将坐标系平移,使点 (0, 0) 位于控件中心,而不是左上角。 我们还将坐标系按 这样,我们便获得了一个 200 × 200 的正方形绘制区域,其原点 (0, 0) 位于中心。我们绘制的图形将显示在该控件中能容纳的最大正方形内。 另请参阅“窗口-视口转换”一节。 我们通过旋转坐标系并调用 `QPainter::drawConvexPolygon()` 来绘制时钟的时针。得益于旋转操作,时针被绘制成指向正确方向。 多边形通过交替排列的x、y值数组来指定,这些值存储在 代码前后分别调用的QPainter::save()和QPainter::restore()确保了后续代码不会受到我们所用变换的影响。 之后,我们绘制时钟表盘上的小时刻度,它由十二条间隔 30 度的短线组成。当该循环结束时,绘图器已经旋转了一圈,回到了原始状态,因此我们无需保存和恢复状态。 对于时钟的分针,我们也采用同样的方法,它由三个点 (7, 8)、(-7, 8)、(0, -70) 定义。这些坐标指定了一根比时针更细、更长的分针。 最后,我们绘制钟面上的分钟刻度,它由六十条以6度间隔排列的短线组成。 我们每隔五个跳过一个分钟刻度,因为不想画到时标上。绘制完成后,绘图器会旋转到一个不太实用的方向,但既然绘制工作已经完成,这也就无所谓了。 | |
有关变换矩阵的更多信息,请参阅QTransform 文档。
窗口-视口转换
使用QPainter 绘图时,我们使用逻辑坐标指定点,这些坐标随后会被转换为绘图设备的物理坐标。
逻辑坐标到物理坐标的映射由QPainter 的世界变换函数worldTransform()(在“变换”一节中描述)以及QPainter 的viewport() 和window() 处理。视口代表指定任意矩形的物理坐标。 “窗口”则用逻辑坐标描述了同一矩形。默认情况下,逻辑坐标系与物理坐标系重合,且等同于绘图设备的矩形。
通过窗口-视口转换,您可以根据需要调整逻辑坐标系。 该机制还可用于使绘图代码与绘图设备解耦。例如,您可以通过调用QPainter::setWindow()函数,将逻辑坐标范围设置为从(-50, -50)到(50, 50),且以(0, 0)为中心:
此时,逻辑坐标 (-50, -50) 对应于绘图设备的物理坐标 (0, 0)。无论绘图设备如何,您的绘图代码都将始终基于指定的逻辑坐标进行操作。
通过设置“窗口”或视口矩形,您对坐标进行了线性变换。请注意,“窗口”的每个角都映射到视口的对应角,反之亦然。因此,通常建议让视口和“窗口”保持相同的纵横比,以防止变形:
int side = qMin(width(), height());
int x = (width() - side / 2);
int y = (height() - side / 2);
painter.setViewport(x, y, side, side);如果我们将逻辑坐标系设为正方形,也应使用QPainter::setViewport()函数将视口设为正方形。 在上例中,我们将视口设置为能刚好容纳在绘制设备矩形内的最大正方形。在设置窗口或视口时考虑绘制设备的大小,可以使绘图代码与绘制设备保持独立。
请注意,窗口到视口的转换仅是一种线性变换,即不会进行裁剪。这意味着,如果你在当前设置的“窗口”之外进行绘制,你的绘制内容仍会通过相同的线性代数方法转换到视口中。
视口、“窗口”和变换矩阵共同决定了QPainter 的逻辑坐标如何映射到绘制设备的物理坐标。 默认情况下,世界变换矩阵为单位矩阵,且“窗口”与视口设置等同于绘制设备的设置,即世界、 “窗口”和设备坐标系是等价的,但正如我们所见,可以通过变换操作和窗口-视口转换来调整这些坐标系。 上图描述了这一过程。
另请参 阅“模拟时钟”。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.








