坐标系由QPainter,QPaintDevice和QPaintEngine控制,从逻辑坐标系到物理坐标系的转换是由变换矩阵,视口与窗口所处理的,并且其中的转换是默认且同步的。
图像图元的尺寸只与数字模型相关,并不在乎画笔设置的宽度值,就像这样:
绘图时,像素渲染通常由QPainter::Antialiasing来设置。
RenderHint变量用来表明QPainter用什么样的engine来渲染,而QPainter::Antialiasing则表明engine如何进行图元边缘的抗锯齿优化。默认情况下绘制是非抗锯齿的,就是说像素都会被渲染在坐标点的右方与下方,像是这样:
当画笔宽度为偶数是,元素会均匀的在数字模型的基础上分散开;如果是奇数,则多出的一个单元将渲染在模型的右下方。也就是这样,QRect::right()和QRect::bottom()与实际的矩形的右下角的位置所不同。因QRect的right()= left()+width()-1, bottom() = top()+height()-1,像图中表示的一样:
像上图的例子,用反走样的绘制方式,应该是这样:
默认情况下QPainter在相关的图形设备上绘制,同时也完全支持仿射变换。可以使用Qpainter::scale(),QPainter::rotate(),QPainter::translate()来实现拉伸,旋转,平移变换,QPainter::shear()来扭曲坐标系。所有的变换都保留在QPainter::worldTransform()所得的矩阵之中。
可以使用QTransform对象来保存变换的值,QPainter::worldTransform()和QPainter::setWorldTransform()方便重用变换。并且同时可以使用QPainter::save()与QPainter::restore()调用变换的堆栈。
视口代表了物理坐标上一个任意的矩形,窗口描述了逻辑坐标上一个相同的矩形。默认情况下两个坐标系是相对应的且矩形是等同的。
使用窗口-视口变换可以使得在逻辑坐标系上进行个性的操作,并且使得绘图代码独立于设备。例如
QPainter painter(this);
painter.setWindow(QRect(-50,-50, 100, 100));
使得(-50,-50)对应于物理坐标的(0,0),逻辑坐标的(0,0)对应于自身100*100方形的中心,于是使得代码可以使用在特定的逻辑坐标系中。
变更窗口或视口,两个矩形都会进行矩形的线形变换,也就是说每个角都是相互对应的,因此保持两个矩形的比例相同可以避免变形:
int side = qMin(width(),height())
int x = (width() - side /2);
int y = (height() - side /2);
painter.setViewport(x, y,side, side);
因为窗口-视口变换是线形的,与剪裁无关,所以如果通过矩阵变换之后,绘制到了矩形之外,同样会按照相同的变换,绘制在矩阵之外无法表现。
默认情况下,变换矩阵为单位矩阵,窗口与视口矩阵是等同的。从默认的逻辑坐标,通过世界矩阵变换,也就是仿射变换,得到窗口坐标;后通过窗口-视口线性变换,得到物理设备上的绘图。