又看QGrphicsItem之旋转

剑神 发布于 2013/07/10 11:22
阅读 2K+
收藏 0

之前对QGrphicsItem进行了自定义和鼠标缩放,后来开始更进一步的操作:旋转。

首先,查看编程手册时发现QGrphicsItem有自己的函数

void QGraphicsItem::setRotation ( qreal angle )
void QGraphicsItem::setTransform ( const QTransform & matrix, bool combine = false )

当然还有一系列的Transform函数对QGraphicsItem进行各种操作,完全可以实现旋转的操作,但是当具体考虑一些比较特殊的状况时,这些操作实际上用起来就比较麻烦了,比如:

我在QGraphicsScene中绘制一个定长定宽“轨道”(一个自定义的QGraphicsItem),在这个轨道上有几架飞机(也是一个自定义的QGraphicsItem),这些飞机根据自己的特定型号(比如说大致的宽高)在轨道之上有自己的位置(比如机舱头所朝的方向),当程序启动的时候,我们可以根据需要通过拖动和旋转来改变这些飞机在轨道上的位置,当然所有的这些设置会保存到一个相应的文件当中。当下一次启动这个程序的时候,我们选择打开上次保存的文件,原封不动的重现上次的情景。

考虑一下上面的情况,我们就需要用其他方法来旋转我们的“飞机”才能更好或者说更简便地实现“保存”和“重现”,那么我所用的是旋转QPainter来实现。首先,轨道可以简单的理解为一个固定长宽的长方形,这个处理很简单;那么关于重写QGraphicsItem实现飞机类的时候,重写的boundingRect()和shape()这两个函数的返回值就需要注意一下,首先是boundingRect()的返回值:

QRectF AirPlane::boundingRect()const{
    qreal max=(this->width()>this->length())?(this->width()):(this->length());
    return QRectF(-(max+1)/2,-(max+1)/2,max,max);
}

如果返回的QRectF的长宽不一样的话会导致我们的飞机在进行旋转操作后进行重绘的时候不能完全画出来(至于为什么,之前的“初始QGraphicsItem”里面貌似说过),而只是残缺的某些部分,而且拖动的时候也会出现这种情况,或者更奇怪的是拖动时的重绘会有图像的残留,而出现“花屏”的效果。另外一个就是shape():

QPainterPath AirPlane::shape()const{
    QPainterPath path;
    qreal max=(this->width()>this->length())?(this->width()):(this->length());
    QRectF rectf=QRectF(-(max+1)/2,-(max+1)/2,max,max);
    path.addRect(rectf);
    return path;
}

这个函数的返回值之所以也是类似的设置是因为当我们需要处理特殊的鼠标事件时,如果这个返回值区域不够大,当“飞机”旋转之后,本来应该接收的一些鼠标事件接收不到。

进行QGraphicsItem重写需要注意的差不多就这些了,那么接下来就是旋转之后的坐标系的问题了,其实这也是我不用QGraphicsItem自己的函数实现旋转的主要原因。如果直接使用QGraphicsItem自己的操作函数进行旋转的时候实际上就是对它自身的坐标系进行旋转,这样我们重绘和进行一些事件处理(比如hoverEnterEvent(QGraphicsSceneHoverEvent *event) )就必须考虑它自身的坐标问题,这个转换就比较麻烦,但是如果我们使用QPainter的rotate()函数来实现旋转的效果的话,我们就不需要管QGraphicsItem的坐标系了,因为我们只是在进行QGraphicsItem绘制的时候对“画笔”画图的方向进行旋转,而QGraphicsItem的坐标系保持不变,这样我们就不需要处理坐标系的变换带来的一系列的问题了。

这里可以提供一个通过旋转QPainter实现旋转效果的例子(QT SDK 4.8.1),如果有什么意见还请多多指教:http://download.csdn.net/detail/rubone/5730221

加载中
返回顶部
顶部