You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QGraphicsItem用setTransform旋转时QTransform不遵循transformOriginPoint,是Bug吗?

QGraphicsItem旋转行为差异:setRotation vs QTransform.setTransform

我发现一个疑似Bug的行为,在提交Qt Bug追踪器前想先确认,避免误解预期行为。问题是:用.setRotation便捷函数和传递QTransform调用.setTransform方法旋转QGraphicsItem时,结果有差异——QTransform方式似乎不遵守QGraphicsItem.setTransformOriginPoint设置的变换原点。

以下是展示该差异的最小可运行示例:

from PySide6 import QtGui
from PySide6.QtWidgets import (
    QApplication,
    QGraphicsRectItem,
    QGraphicsScene,
    QGraphicsView,
    QMainWindow,
    QPushButton,
    QVBoxLayout,
    QWidget,
)


class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.layout = QVBoxLayout()
        self.central_widget = QWidget(self)
        self.setCentralWidget(self.central_widget)
        self.central_widget.setLayout(self.layout)

        self.view = QGraphicsView()
        self.layout.addWidget(self.view)
        self.scene = QGraphicsScene(self)
        self.view.setScene(self.scene)

        self.rectangle = QGraphicsRectItem(0, 0, 500, 275)
        pen = QtGui.QPen()
        pen.setWidth(25)
        pen.setColor("Yellow")
        self.rectangle.setPen(pen)

        self.scene.addItem(self.rectangle)

        self.button_with_QTransform = QPushButton(
            text="Rotate Using QTransform",
            parent=self,
        )
        self.button_without_QTransform = QPushButton(
            "Rotate without QTransform",
            self,
        )
        self.layout.addWidget(self.button_with_QTransform)
        self.layout.addWidget(self.button_without_QTransform)
        self.button_with_QTransform.clicked.connect(
            self.transform_rectangle_with_QTransform
        )
        self.button_without_QTransform.clicked.connect(
            self.transform_rectangle_without_QTransform
        )
        self.rectangle.setTransformOriginPoint(self.rectangle.boundingRect().center())
        self.current_rotation = 0

    def transform_rectangle_with_QTransform(self):
        self.current_rotation += 10
        transform = QtGui.QTransform()
        transform.rotate(self.current_rotation)
        self.rectangle.setTransform(transform)

    def transform_rectangle_without_QTransform(self):
        self.current_rotation += 10
        self.rectangle.setRotation(self.current_rotation)


def main():
    app = QApplication()
    window = MyWindow()
    window.show()
    window.showMaximized()
    app.exec()


if __name__ == "__main__":
    main()

这不是Bug,是两种API的设计逻辑差异导致的:

  • .setRotation()是QGraphicsItem提供的便捷方法,内部会自动结合你通过setTransformOriginPoint()设置的原点处理变换:先将元素平移到原点位置,执行旋转后再平移回原位置,最终实现围绕指定原点旋转的效果。
  • 直接调用setTransform(QTransform())时,你创建的QTransform是基于坐标系原点(0,0)的旋转,不会自动关联QGraphicsItem的transformOriginPoint设置。如果要和.setRotation()得到一致的效果,需要手动构建包含原点平移的变换链:

修改后的transform_rectangle_with_QTransform方法示例:

def transform_rectangle_with_QTransform(self):
    self.current_rotation += 10
    origin = self.rectangle.transformOriginPoint()
    transform = QtGui.QTransform()
    # 先平移到变换原点
    transform.translate(origin.x(), origin.y())
    # 执行旋转
    transform.rotate(self.current_rotation)
    # 平移回原位置
    transform.translate(-origin.x(), -origin.y())
    self.rectangle.setTransform(transform)

简言之,QGraphicsItem的便捷变换方法(如setRotation、setScale)会封装原点处理逻辑,而直接操作QTransform时,需要手动处理坐标平移,因为QTransform本身是独立的变换矩阵,不感知QGraphicsItem的原点配置。

内容的提问来源于stack exchange,提问作者user2752148

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 20:17:33