世界变化(QTransform )是在窗口-视口转换之外使用的变换矩阵。它允许移动、缩放、旋转或者拉伸绘制的项。
QTransform 比 QMatrix 先进,之前版本用 QMatrix。推荐使用 QTransform。
QTransform 与 QMatrix 不同之处在于,它是一个真正的 3x3 矩阵,允许视角转换,QTransform 的 toAffine() 方法允许将 QTransform 转换到QMatrix。如果视角转换已在矩阵指定,则转换将导致数据丢失。
一、平移
1. 设定左上角为原点坐标(0,0),在视口(200,200)的位置绘制一个边长为200的矩形。如下所示:
void QtWidgetTest::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(QPen(Qt::blue, 1, Qt::DashDotLine));
painter.setBrush(Qt::red);
QTransform transform;
// transform.translate(100, 100); // 平移
// painter.setTransform(transform);
QPoint point = transform.map(QPoint(200, 200));
qDebug() << "TEST --point = " << point;// 输出为(200,200)
painter.drawRect(point.x(), point.y(), 200, 200);
// 绘制网格线
QPainter painter1(this);
painter1.setPen(QPen(Qt::black, 1, Qt::DashLine));
int nTemp = 200;
QList list{ 100, 200, 300, 400, 500 };
foreach(int nTemp, list)
{
painter1.drawRect(0, 0, nTemp, nTemp);
painter1.drawText(QPoint(nTemp + 10, 10), QString("%1").arg(nTemp));
painter1.drawText(QPoint(10, nTemp + 10), QString("%1").arg(nTemp));
}
painter1.drawLine(0,0,1000,1000);
}
2. 使用世界坐标转换平移(100,100),将上面代码“transform.translate(100, 100); // 平移”注释去掉,如下所示:
void QtWidgetTest::paintEvent(QPaintEvent *event)
{
...
transform.translate(100, 100); // 平移
// painter.setTransform(transform);
QPoint point = transform.map(QPoint(200, 200));
qDebug() << "TEST --point = " << point;// 输出为(300,300)
painter.drawRect(point.x(), point.y(), 200, 200);
...
}
在(200,200)点输出的坐标,经过平移转换后,point位置为(300,300),输出结果如下:
3. 如果使用变化后QTransform 作为坐标系,将上面代码“painter.setTransform(transform);”注释去掉,如下所示:
void QtWidgetTest::paintEvent(QPaintEvent *event)
{
...
transform.translate(100, 100); // 平移
painter.setTransform(transform);
QPoint point = transform.map(QPoint(200, 200));
qDebug() << "TEST --point = " << point;// 输出为(300,300)
painter.drawRect(point.x(), point.y(), 200, 200);
...
}
在(200,200)点输出的坐标,经过平移转换后,point位置仍为(300,300),但绘制的结果相对坐标原定(100,100),绘出的位置为(400,400),这只是视口的显示结果。
二、缩放
1. 设定左上角为原点坐标(0,0),在视口(200,200)的位置绘制一个边长为200的矩形。缩放比例为0.1倍,如下所示:
void QtWidgetTest::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(QPen(Qt::blue, 1, Qt::DashDotLine));
painter.setBrush(Qt::red);
QTransform transform;
//transform.translate(100, 100);
transform.scale(0.1, 0.1);
// painter.setTransform(transform);
QPoint point = transform.map(QPoint(200, 200));
qDebug() << "TEST --point = " << point; // 输出(20,20)
painter.drawRect(point.x(), point.y(), 200, 200);
// 绘制网格线
...
}
坐标点(200,200)经过缩放,输出的坐标为(20,20)。在输出位置绘制一个边长为200的矩形,如下图所示:
2. 如果使用变化后QTransform 作为坐标系,将上面代码“painter.setTransform(transform);”注释去掉,如下所示:
void QtWidgetTest::paintEvent(QPaintEvent *event)
{
...
QTransform transform;
//transform.translate(100, 100);
transform.scale(0.1, 0.1);
painter.setTransform(transform);
QPoint point = transform.map(QPoint(200, 200));
qDebug() << "TEST --point = " << point; // 输出(20,20)
painter.drawRect(point.x(), point.y(), 200, 200);
// 绘制网格线
...
}
point输出的坐标仍然是(20,20),以QTransform 作为坐标系,在视口进行显示时,按0.1的比例进行显示。转换后,矩形左上角位置应该为(2,2),边长为20。逻辑坐标的数据依然为左上角(20,20),边长为200。
三、平移+缩放
1. 在上面代码的基础上,增加代码transform.translate(100, 100);,如下所示:
void QtWidgetTest::paintEvent(QPaintEvent *event)
{
...
QTransform transform;
transform.translate(100, 100);
transform.scale(0.1, 0.1);
painter.setTransform(transform);
QPoint point = transform.map(QPoint(200, 200));
qDebug() << "TEST --point = " << point; // 输出(20,20)
painter.drawRect(point.x(), point.y(), 200, 200);
// 绘制网格线
...
}
按照上面的逻辑,QPoint(200, 200)转换为(120,120),不是(140,140),相当于在点(120,120)的位置绘制一个边长为200的矩形。
由于使用缩放和平移,以(120,120)缩放至(12,12),边长缩放至20,以平移的(100,100)为原点,所以输出位置为(112,112)。