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
相关产品推荐
相关产品推荐

