精通Qt4编程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

6.2 坐标系统与坐标变换

6.2.1 坐标系统

Qt的坐标由QPainter控制,同时也由QPaintDevice和QPaintEngine类控制。QPaintDevice类是绘图设备的基类,QWidget、QPixmap、QImage和QPrinter都是QPaintDevice的子类。Qt的绘图设备默认坐标系统是坐标原点在左上角,X轴向右增长,Y轴向下增长。默认的单位在基于像素的设备上是像素,在打印机上则是1/72英寸(约等于0.35毫米)。

QPainter的逻辑坐标与QPainterDevice的物理坐标之间的映射由QPainter的变换矩阵、视口和窗口处理。逻辑坐标与物理坐标默认是一致的。QPainter也支持坐标变换(如旋转和伸缩)。

6.2.2 坐标变换

通常QPainter在设备的坐标系统上绘制图形,但QPainter也支持坐标变换。可以通过QPainter::scale()函数进行比例变换;可以使用QPainter::rotate()函数进行旋转变换;平移变换则使用QPainter::translate()函数;QPainter::shear()函数对图形进行扭曲操作。所有变换操作的变换矩阵都可以通过QPainter::worldMatrix()函数取出。不同的变换矩阵可以使用堆栈保存,用QPainter::save()保存变换矩阵到堆栈,用QPainter::restore()函数将其弹出堆栈。

为了实现更复杂的变化,可以使用QTransform定义坐标系统的二维变换。QTransform对象实际上是一个3×3的变换矩阵,其模型如图6-11所示。

图6-11 QMatrix变换矩阵

其中dx、dy表示水平和垂直平移量,m11和m22表示水平和垂直方向的比例。m12和m21表示水平和垂直方向的扭曲程度。m13和m23表示水平和垂直投影。m33为投影因子。

QTransform将一点变换为另外一点的公式如下所示:

x′=m11×x+m21×y+dx

y′=m22×y+m12×x+dy

其中(x,y)是变换前的点,(x',y')是变换后的点。

矩阵可以通过setMatrix()函数进行设置,然后可以使用translate()、rotate()、scale()和shear()等函数进行变换。

在QPainter上绘制使用的是逻辑坐标,Qt再将其变换为绘图设备上的物理坐标。逻辑坐标与物理坐标的变换由QPainter的worldMatrix()函数,以及QPainter的viewport()和window()函数处理。视口表示物理坐标下的任意矩形,而窗口表示在逻辑坐标下的相同矩形。默认情况下逻辑坐标与物理坐标是相同的,与绘图设备上的矩形也是一致的。

使用窗口—视口变换可以使逻辑坐标符合自定义要求。这个机制通常用来完成与设备无关的绘图代码。例如,可以设置逻辑坐标(-100,-100)到(100,100)且原点在(0,0),通过调用QPainter::setWindow()函数可以完成这个操作:

        QPainter painter(this);
        painter.setWindow(QRect(-100, -100, 200, 200));

现在,逻辑坐标的(-100, -100)对应着绘图设备的物理坐标(0,0)。这样可以独立于绘图设备,始终在指定的逻辑坐标上工作。

设置窗口或视口矩形实际上是执行线性变换。本质上是窗口四个角映射到相应的视口四个角,反之亦然。因此保持视口和窗口X轴和Y轴之间的变换比例一致,保证变换没有变形。

窗口—视口变换只是线性变换,不执行裁剪等操作。例如当绘制超出了窗口时,这些绘制仍会通过线性变换映射到视口进行绘制。

Qt的绘制过程是先进行坐标变换,再进行窗口—视口变换。