Qt中的坐标变换

在QWidget中绘图,需要经过两次坐标变换:1、将World坐标转换为Window坐标。2、将Window坐标转换为设备坐标。下面分别描述

1、World坐标转换为Window坐标
在Qt中,Window坐标是这个二维绘图区域的逻辑坐标,向左x增长,向下y增长。但是,我们定义图元时使用的坐标系统可能和Qt的定义不同,因此需要通过坐标变换将world坐标转换为Window坐标。Qt使用QTransform表示坐标变换矩阵。

2、Window坐标转换为设备坐标

Qt最终要在设备上完成绘图,因此需要将Window坐标转换为设备的坐标,如(QWidget坐标)。一般设备坐标都是以实际的像素为单位,而逻辑坐标则没有这个限制。这样就很方便,可以按照绘制内容的坐标设定Window坐标。比如,我们想要绘制一幅图像,在Window坐标按照图像的尺寸指定矩形区域(setWindow()),然后在这个矩形区域中绘图,而不需要考虑显示窗口(QWidget)实际的尺寸。要将在逻辑空间中(Window坐标)绘制的图像在窗口中显示,需要在窗口中定义一个矩形区域(setViewport()),与逻辑空间的矩形区域匹配,有了这两个矩形,绘图系统就知道需要如何进行坐标变换,将Window坐标转换为设备坐标。可以调用deviceTransform()得到这个变换矩阵。


经验:

如果假设Window坐标与设备坐标一致(默认情况),那么通过World-Window坐标变换就可以完成World坐标到设备坐标的转换。这样做有一个好处,就是可以保存World-Window变换矩阵m,绘图时设置变换矩阵painter.setTransform()完成World-Window坐标转换;当就是当需要一个反向变换时(设备坐标到World坐标),如将鼠标事件的坐标(为设备坐标)转换为world坐标,只需要将m求逆就可以得到方向映射矩阵了。


注释:

使用deviceTransform()可得到window-device的变换矩阵,但是得到的并不是当前Widget的变换矩阵,好像是整个应用程序窗口的变换矩阵(即包含当前窗口的平移量)。用这个矩阵进行反向转换坐标就会不对。

本资源为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、付费专栏及课程。

余额充值