Qt中旋转平移单个图形项应优先使用setTransform()配合QTransform,先rotate再translate实现绕原点旋转后平移,绕自定义中心需先负向平移再旋转再正向平移;setRotation()和rotate()仅影响rotation状态值且依赖setTransformOriginPoint(),而QGraphicsView的rotate()/translate()只改变视图显示不改变场景逻辑坐标。

QGraphicsItem::setTransform() 是最直接的旋转平移方式
Qt 中对单个图形项做旋转、平移,首选不是改 pos() 或硬算坐标,而是用变换矩阵。调用 setTransform() 可一次性叠加旋转、平移、缩放,且不影响物理坐标系(boundingRect() 和碰撞检测仍基于原始形状)。
常见错误是先调 setRotation() 再调 setPos(),结果平移被旋转中心干扰——因为 setRotation() 默认绕自身原点(通常是左上角)转,而 setPos() 移动的是整个 item 的锚点,二者顺序和参考系不一致。
- 正确做法:构造
QTransform,用rotate()和translate()链式调用,注意顺序——先旋转再平移,等价于“绕原点转完,再挪到目标位置” - 若需绕自定义中心(如图形中心)旋转,先
translate(-cx, -cy),再rotate(),再translate(cx, cy) -
setTransform()默认会重置之前的变换,如需叠加,传True作为第二个参数:item.setTransform(transform, True)
QTransform t; t.translate(100, 50); // 先平移到 (100, 50) t.rotate(45); // 再绕 (0,0) 旋转 45° item.setTransform(t);
QGraphicsView::rotate() 和 ::translate() 只影响视图,不改变场景
这两个函数操作的是视图的显示层,类似给整个画布加滤镜:调用后所有 item 看起来旋转/偏移了,但它们在 QGraphicsScene 中的逻辑位置、坐标、大小全都没变。适合做 UI 动效或临时预览,不适合精确控制单个图形运动。
典型误用场景:想让某个按钮图标旋转,却对 QGraphicsView 调 rotate(),结果整个场景跟着转,其他控件也歪了。
-
view.rotate(30)等价于view.setTransform(QTransform().rotate(30), True) - 视图变换会累积,多次调用需手动
resetTransform()清理,否则缩放失真、坐标映射错乱 - 如果后续要用
mapToScene()或mapFromScene()做坐标转换,必须考虑当前视图变换,否则点击位置计算错误
用 QGraphicsItemAnimation 已废弃,改用 QPropertyAnimation + setTransform()
QGraphicsItemAnimation 在 Qt 5.0 就被标记为 deprecated,Qt 6 中已移除。现在标准做法是用 QPropertyAnimation 动画化 item 的 transform 属性。
关键点在于:必须先用 QObject.setProperty() 把变换逻辑封装成可动画属性,或者子类化 QGraphicsItem 并声明 Q_PROPERTY;否则 QPropertyAnimation 找不到目标属性。
- 简单方案:子类化 item,添加
rotation和position属性,setter 内部调用setTransform() - 更轻量做法:用
QVariantAnimation,在valueChanged信号里手动更新setTransform() - 避免在动画中频繁新建
QTransform对象——复用一个实例并调setMatrix()更高效
rotate() 和 setRotation() 的区别:一个改视觉,一个改状态
QGraphicsItem::rotate() 是相对旋转(在当前角度基础上再转),而 setRotation() 是绝对设置(直接设成某度数)。但二者都只修改 item 的 rotation 状态值,并自动触发内部变换更新——它们底层仍是调用 setTransform() 构造旋转矩阵。
问题常出在混合使用:比如先 setRotation(30),再 rotate(10),你以为总转 40°,但如果中间有 setTransform() 调用,rotation 状态可能被清零或覆盖,导致行为不可预期。
- 纯角度控制场景,优先用
setRotation()+setTransformOriginPoint()明确旋转中心 - 需要同时控制角度+位移时,放弃
rotate()/setRotation(),统一走setTransform()流程,避免状态与变换脱节 -
setTransformOriginPoint()只对setRotation()/setScale()生效,对setTransform()无效——这点极易忽略
真正麻烦的从来不是怎么写那几行代码,而是搞清「谁在哪个坐标系里动」「变换是否叠加」「状态和实际渲染是否同步」。Qt 的变换接口看似多,其实就两条路:动 item 本身,用 setTransform();动镜头,用 QGraphicsView 的变换。混着用,八成出事。

















