QPainter在窗口上绘图的默认坐标系统如图,这是绘图设备的物理坐标。为了绘图 的方便,QPainter提供了一些坐标变换的功能,通过平移、旋转等坐标变换,得到一个逻辑坐标 系统,使用逻辑坐标系统在某些时候绘图更方便。
QPainter 绘制的坐标变换的函数如下:
如下图所示,在默认坐标系统下,我们绘制一条直线。
QPainter painter(this);
painter.drawLine(QPoint(20, 20), QPoint(40, 40));
执行结果如下图所示。
然后,我们将坐标系旋转90度,再绘制一条直线,会发现再窗口里面什么都没有,这是因为坐标系旋转之后,绘制的图形在窗口外面,所以就看不见。
QPainter painter(this);
painter.rotate(90);
painter.drawLine(QPoint(20, 20), QPoint(40, 40));
通过平移函数,将坐标系原点移动到指定的位置。
QPainter painter(this);
painter.translate(200, 200);
painter.drawLine(QPoint(0, 0), QPoint(40, 40));
通过平移坐标系就会移动到指定的位置,如图所示:
在将坐标系移动到指定位置之后,此时我们再旋转坐标系进行绘制,就会发现能够进行绘图了。这是因为移动了坐标系之后,旋转坐标系,这个坐标系绘制的图案还处在这个窗口内,所以就能看见。
QPainter painter(this);
painter.translate(200, 200);
painter.rotate(90);
painter.drawLine(QPoint(0, 0), QPoint(40, 40));
如图所示:
如上图,所示,通过移动坐标原点,就能实现旋转坐标系后的重新绘图,接下来,我们通过旋转来绘制一个圆。
QPainter painter(this);
QPen pen;
pen.setColor(QColor(78, 128, 233));
pen.setWidth(2);
painter.setPen(pen);
painter.translate(200, 200);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.save();
for (int i=0; i< 360;)
{
painter.save();
painter.translate(200, 200);
painter.rotate(i);
painter.drawLine(QPoint(0, 0), QPoint(40, 40));
painter.restore();
i += 1;
}
运行结果如下图所示:
当然我也可以通过,旋转的角度和不同的画笔宽度,和形状来绘制不同的图案,例如绘制一个雪花:
QPainter painter(this);
QPen pen;
pen.setColor(QColor(78, 128, 233));
pen.setWidth(10);
painter.setPen(pen);
painter.translate(200, 200);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.save();
for (int i=0; i< 360;)
{
painter.save();
painter.translate(200, 200);
painter.rotate(i);
painter.drawLine(QPoint(0, 0), QPoint(40, 40));
painter.restore();
i += 40;
}
绘图设备的物理坐标是基本的坐标系,通过QPainter的平移、旋转等变换可以得到更容易操 作的逻辑坐标。
为了实现更方便的坐标, QPainter还提供了视口(Viewport)和窗口(Window)坐标系,通 过QPainter内部的坐标变换矩阵自动转换为绘图设备的物理坐标。
视口表示绘图设备的任意一个矩形区域的物理坐标,可以只选取物理坐标的一个矩形区域用 于绘图。默认情况下,视口等于绘图设备的整个矩形区。
窗口与视口是同一个矩形,只不过是用逻辑坐标定义的坐标系。窗口可以直接定义矩形区的 逻辑坐标范围。
程序的界面代表绘图设备的物理大小和坐标范围。我们再界面上取一块区域作为视口,灰色的正方形就是视口的大小。
painter.setViewport(50,0,200,200);
表示从绘图设备物理坐标系统的起点(50,0)开始,取宽度为200、高度为200的一个矩形区域 作为视口。对于视口的正方形区域,定义一个窗口,窗口的坐标中心在正方形的中心,并设置正方形的逻辑边长为100。可使用QPainter的setWindow()函数。
painter.setWindow(-50,-50,100,100);
它表示对应于视口的矩形区域,其窗口左上角的逻辑坐标是(-50,-50),窗口宽度为100,高度 为100。这里设置的窗口还是一个正方形,使得从视口到窗口变换时,长和宽的变化比例是相同 的。实际可以任意指定窗口的逻辑坐标范围,长和宽的变化比例不相同也是可以的。
使用窗口坐标的优点是,只需按照窗口坐标定义来绘图,而不用管实际的物理坐标范围的大小。 例 如在一个固定边长为100的正方形窗口内绘图,当实际绘图设备大小变化时,绘制的图形会自动变化大 小。这样,就可以将绘图功能与绘图设备隔离开来,使得绘图功能适用于不同大小、不同类型的设备。
QPainter painter(this);
int W = width();
int H = height();
int side = qMin(W, H)/2;//取长和宽的小值
QRect rect((W - side) / 2, (H - side) / 2, side, side); //viewport矩形区
painter.drawRect(rect); //Viewport大小
painter.setViewport(rect);//设置Viewport
painter.setWindow(-100, -100, 200, 200); // 设置窗口大小,逻辑坐标
painter.setRenderHint(QPainter::Antialiasing);//抗锯齿
//设置画笔
QPen pen;
pen.setWidth(1); //线宽
pen.setColor(Qt::red); //划线颜色
pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等
painter.setPen(pen);
for (int i = 0; i < 36; i++)
{
painter.drawLine(0, 0, 50, 50);
painter.rotate(10);
}
运行结果如下图所示:
------------------
绘制的图形,会随着程序窗口的大小而改变。
作者在学习了这部分知识之后加入了自己的理解,作为记录。原文在此处。