Qt坐标变换详解

Qt坐标变换详解

在图形编程中,坐标变换是非常重要的概念,它可以帮助我们方便地进行平移、旋转、缩放和剪切等操作。在Qt中,QPainter 提供了丰富的坐标变换功能,使得复杂的图形操作变得简单。本文将通过具体的示例代码,详细讲解Qt中常用的坐标变换方法。

初始化 QPainter

在开始绘制之前,我们需要创建一个 QPainter 对象并启用抗锯齿功能,以提高绘图的质量。以下代码展示了如何初始化 QPainter

QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::TextAntialiasing);

通过设置抗锯齿和文本抗锯齿,可以使绘制的图形和文字更加平滑,避免锯齿现象。Antialiasing 主要用于平滑图形边缘,而 TextAntialiasing 则用于平滑文本的边缘。

设置画笔和字体

在绘制图形和文字之前,需要设置画笔和字体的属性。以下代码展示了如何设置画笔和字体:

QPen pen;
pen.setWidth(4);
pen.setColor(Qt::red);
painter.setPen(pen);

QFont font;
font.setPointSize(20);
painter.setFont(font);

这里我们创建了一个 QPen 对象,并将其宽度设置为4,颜色设置为红色。然后将该画笔应用于 QPainter。同时,我们创建了一个 QFont 对象,并将其大小设置为20,然后将该字体应用于 QPainter。这使得接下来绘制的图形使用红色线条,并且绘制的文本使用大小为20的字体。

坐标平移

坐标平移是将绘图的原点从一个位置移动到另一个位置。以下代码展示了如何使用 translate() 方法进行坐标平移:

QRect imageRect(100, 100, 400, 300);
QImage image(":/JINGMAO.jpg");
painter.drawImage(imageRect, image);

// 坐标平移
painter.translate(400, 300);
painter.drawImage(imageRect, image);

在这段代码中,第一次绘制图片时使用了原始坐标 (100, 100)(500, 400) 的矩形区域。然后,使用 painter.translate(400, 300) 将坐标系平移到 (400, 300) 位置,再次绘制相同的图片。通过这种方式,图片会被绘制到新的位置 (500, 400)(900, 600)。坐标平移使我们可以方便地改变绘图的位置,而不需要更改具体的绘制代码。

坐标旋转

坐标旋转是将整个坐标系绕原点旋转一定的角度。以下代码展示了如何使用 rotate() 方法进行坐标旋转:

painter.resetTransform(); // 重置变换
painter.drawImage(imageRect, image);

// 坐标旋转
painter.rotate(30); // 旋转30度
painter.drawImage(imageRect, image);

在这段代码中,首先绘制了原始图片。然后,使用 painter.rotate(30) 将坐标系顺时针旋转30度,再次绘制相同的图片。通过这种方式,图片会以原点为中心进行旋转。需要注意的是,旋转是以当前坐标系的原点为中心进行的,原点的位置也会随平移操作而改变。旋转操作通常用于需要绘制特定角度的图形或在特定角度绘制文本的场景。

坐标扭转

坐标扭转(剪切)是将坐标系中的网格线进行倾斜。以下代码展示了如何使用 shear() 方法进行坐标扭转:

painter.resetTransform(); // 重置变换
painter.drawImage(imageRect, image);

// 坐标扭转
painter.shear(0.1, 0.1); // x方向和y方向各剪切0.1
painter.drawImage(imageRect, image);

在这段代码中,首先绘制了原始图片。然后,使用 painter.shear(0.1, 0.1) 将坐标系的x方向和y方向各剪切0.1,再次绘制相同的图片。通过这种方式,图片会发生倾斜。剪切变换可以用来创建逼真的透视效果或斜体文本效果。剪切操作改变了坐标系的形状,使得水平和垂直方向上的网格线不再平行,从而产生倾斜效果。

坐标缩放

坐标缩放是将坐标系按比例放大或缩小。以下代码展示了如何使用 scale() 方法进行坐标缩放:

painter.resetTransform(); // 重置变换
painter.drawImage(imageRect, image);

// 坐标缩放
painter.scale(0.5, 0.5); // 缩小到50%
painter.drawImage(imageRect, image);

在这段代码中,首先绘制了原始图片。然后,使用 painter.scale(0.5, 0.5) 将坐标系缩小到原来的50%,再次绘制相同的图片。通过这种方式,图片会按比例缩小。缩放操作可以用来改变图形或文本的大小,而无需修改其定义。需要注意的是,缩放会同时影响水平和垂直方向,因此可以实现各种比例的放大或缩小效果。

保存和恢复坐标状态

在进行多次复杂的变换时,保存和恢复坐标状态非常有用。以下代码展示了如何使用 save()restore() 方法进行操作:

QRect imageRect(0, 0, 400, 300);
QImage image(":/JINGMAO.jpg");
painter.drawImage(imageRect, image);

// 保存坐标状态
painter.save();

// 进行变换
painter.shear(0.1, 0.1);
painter.drawImage(imageRect, image);

// 恢复坐标状态
painter.restore();
painter.drawImage(imageRect, image);

在这段代码中,首先绘制了原始图片。然后,使用 painter.save() 保存当前的坐标状态。接下来,进行剪切变换并绘制图片。最后,使用 painter.restore() 恢复到保存的坐标状态,再次绘制相同的图片。通过这种方式,可以方便地在复杂变换之间切换,而无需手动恢复每一步变换。保存和恢复坐标状态特别适用于需要在同一绘制操作中应用多种变换的情况。

复位所有的坐标变换

在某些情况下,需要复位所有的坐标变换,使坐标系回到初始状态。以下代码展示了如何使用 resetTransform() 方法复位坐标变换:

painter.resetTransform(); // 复位所有的坐标变换
painter.drawImage(imageRect, image);

在这段代码中,使用 painter.resetTransform() 方法复位所有的坐标变换。通过这种方式,坐标系将回到初始状态,之后的绘制操作将不受之前变换的影响。resetTransform() 方法清除了所有的平移、旋转、缩放和剪切变换,使得坐标系恢复到默认状态。这在需要清除所有变换并重新开始绘制时非常有用。

综合示例:绘制五角星

最后,我们将以上的知识点结合起来,绘制一个五角星。以下代码展示了如何计算五角星的顶点并进行绘制:

qreal r = 200;
qreal PI = 3.14159;
qreal unit = 72 * PI / 180;
QPoint points[5] = {
    QPoint(r, 0),
    QPoint(r * cos(unit), -r * sin(unit)),
    QPoint(r * cos(2 * unit), -r * sin(2 * unit)),
    QPoint(r * cos(3 * unit), -r * sin(3 * unit)),
    QPoint(r * cos(4 * unit), -r * sin(4 * unit))
};
QPainterPath starPath;
starPath.moveTo(points[0]);
starPath.lineTo(points[2]);
starPath.lineTo(points[4]);
starPath.lineTo(points[1]);
starPath.lineTo(points[3]);
starPath.closeSubpath();

starPath.addText(points[0], font, "0");
starPath.addText(points[1], font, "1");
starPath.addText(points[2], font, "2");
starPath.addText(points[3], font, "3");
starPath.addText(points[4], font, "4");

painter.save();
painter.translate

(r * 1.2, r * 1.1);
painter.rotate(-18);
painter.drawPath(starPath);
painter.restore();

解释

  1. 计算五角星顶点:使用三角函数计算五角星的五个顶点坐标。通过将极坐标转换为直角坐标,计算出每个顶点的位置。
  2. 创建路径:使用 QPainterPath 对象定义五角星的路径,并连接各个顶点。moveTo 方法将路径起点移动到第一个顶点,然后使用 lineTo 方法依次连接其他顶点。
  3. 添加文本标签:在每个顶点位置添加相应的文本标签。使用 addText 方法在路径上添加文本,标记每个顶点的位置。
  4. 保存状态并变换坐标系:使用 painter.save() 保存当前坐标状态,使用 painter.translate()painter.rotate() 进行平移和旋转变换。
  5. 绘制五角星并恢复状态:使用 painter.drawPath() 绘制五角星,然后使用 painter.restore() 恢复到保存的坐标状态。

通过以上代码,我们成功绘制了一个红色的五角星,每个顶点上标有相应的数字。利用Qt提供的坐标变换功能,使得绘制复杂图形变得更加简单和直观。

总结

Qt提供了丰富的坐标变换功能,包括平移、旋转、剪切和缩放等,使得图形编程更加灵活和强大。通过 save()restore() 方法,可以方便地管理和切换不同的变换状态。掌握这些坐标变换方法,将极大地提升我们在Qt中进行图形绘制的能力。

  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本资源为Qt绘图基础,世界坐标系转换为逻辑坐标系。世界坐标系原点在视图左上角,本例子通过世界坐标转换,将坐标原点定位在视图中央,Y轴向上,X轴向右,并绘制坐标轴,基于逻辑坐标系下的绘图,可将转换关系函数取消生效,对比世界坐标系下的绘图。 重写PainterEvent函数: void QtPixPainter::paintEvent(QPaintEvent* event) { QPainter painter(this); // 反走样 painter.setRenderHint(QPainter::Antialiasing, true); //物理坐标系与逻辑坐标系的转换,如果不转换,下面的绘图都是在世界坐标系下 setWorldTransform(painter); // 其他一些绘制矩形,多边形的例子,经过上面转换,都是在逻辑坐标系下 drawRectScale(painter); //draw_shearRect(painter); //利用rotate()函数进行比例变换,实现缩放效果 //draw_rotate_act(painter); //draw_by_save_restore(painter); //transform_draw_SinX(painter); transform_draw(painter); local_drawConvexPolygon(painter); } // 将世界坐标(原点左上角)转换为逻辑坐标(原点在屏幕中间) QPointF QtPixPainter::mapToScene(const QPointF& point) { QTransform transMatrix = _transform.inverted(); //翻转矩阵? return transMatrix.map(point); //将点piont映射到transMatrix定义的坐标系中来 } // 将鼠标的逻辑位置返回并以标签形式展示 void QtPixPainter::mouseMoveEvent(QMouseEvent* event) { QString msg; QPointF mouse_po = mapToScene(event->pos()); //总是返回屏幕物理坐标系 double x = mouse_po.x(); // 总是返回屏幕物理坐标系 double y = mouse_po.y(); QString str = "(" + QString::number(x) + "," + QString::number(y) + ")"; //qDebug()<<"world x = "<pos().x()<<",world y = "<pos().y(); m_mouse_lable->setText(str); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值