使用 QLineF 从 QTransform 提取角度信息
我们在对 QGraphicsItem 进行变换时QT 提供了很多便捷的方法。但当我们想获取当前变换的角度时却有些困难因为 QTransform 没有提供获取角度的方法。在文章Qt 从 QTransform 逆向解出 Translate/Scale/Rotate平移/缩放/旋转分析 分析过使用 QTransform 进行多种变换组合后由于组合顺序不能预知、组合数量不能预知很难从 QTransform 矩阵中推算出当前变换的角度。即使推算出来由于切变、缩放等变换的影响推算出的角度也不准确。结合 QLineF 可以有个简便的方式来倒推变换角度。一、从 QGraphicsItem 的变换说起对 QGraphicsItem 进行变换有三种方式1. 使用 setRotation() 或 setScale()2. 使用 setTransform()3. 使用 setTransformations()如果同时使用多种方式变换效果将进行叠加。变换按照固定的顺序进行第一步应用 transform() 指定的变换第二步应用 transformations() 指定的变换第三步应用 rotation(), transformOriginPoint() 指定的变换第四步应用 scale(), transformOriginPoint() 指定的变换如果使用 setTransform() 指定旋转角度 A再使用 setRotation() 指定旋转角度 B那么 QGraphicsItem 旋转的角度就是 A B。使用 rotation() 获取的角度值是 B角度 A 只能从 transform() 中推算。然后使用 resetTransform() 复位的是 transform()rotation() 中的角度仍然保留那么此时 QGraphicsItem 旋转的角度就是 B 。也就是说三种变换方式数值的变换相互不影响。对于有父子关系的 QGraphicsItem 父项目的变换将累加到子项目(即使在父项目中使用的是setRotation()方式进行的变换叠加到子项目时只能从transform中获取该角度并不会影响到子项目的 rotation())子项目通过方法 sceneTransform() 获取所有累加的变换通过 scenePos() 获取子项目在 scene 上的坐标。二、解析 QGraphicsItem 当前旋转的角度直接作用于 QGraphicsItem 的角度不考虑父节项目对 QGraphicsItem 的影响或者 QGraphicsItem 没有父项目时计算 QGraphicsItem 当前旋转的角度需要分别考虑 setRotation()、setTransform() 和 setTransformations() 设置的角度分别计算后再进行累加即可。如果 QGraphicsItem 没有父项目可以使用 sceneTransform() 获取所有累加变换后的 transform从 transform 推算角度。有父项目的 QGraphicsItem 的角度考虑父项目对 QGraphicsItem 的变换影响直接使用 sceneTransform() 获取所有累加变换后的 transform再推算角度。三、使用 QLineF 从 transform 提取角度QLineF 提供的方法 angleTo() 可以帮助我们方便的计算2条直线间的夹角。要从 transform 中计算角度可以先构建一条直线然后使用 QTransform 的 map() 方法对直线进行变换。变换后的直线与原直线间的夹角就是 transform 旋转的角度。示例代码如下QTransform trans item-sceneTransform(); QLineF line1{{0,0},{1,0}}; QLineF line2 trans.map(line1); qreal angle line2.angleTo(line1)注意如果 transform 中执行过 shear 变换该方法推算出来的角度不是原来设置的角度。