旋转 - 变换原点 - PyQt4

1 投票
2 回答
2016 浏览
提问于 2025-04-17 14:11

我在用PyQt做一个小的用户界面。

这个界面里有一个窗口,一个按钮(旋转),还有一个多边形(矩形)放在QGraphicsView里。这个应用的一个目标是让用户可以旋转这个多边形。也就是说,当用户点击按钮后,再点击一个点,离这个点最近的顶点就会自动向用户点击的地方移动或倾斜。我还设置了在点击之前多边形可以移动,点击之后就不能再移动了。

问题是,如果用户先移动了多边形,然后再点击,结果多边形的旋转就会变得很奇怪。有人能帮我找出错误吗?我猜可能是和setTransformOriginPoint有关。

补充说明:我有两个类,分别继承自QtGui.QWidget和QtGui.QGraphicsScene。

class Window(QtGui.QWidget):
    def polychange(self , sender): //Called by the button , 
        if sender:
                self.view.polyrotate = 1 //self.view is an instance of QGraphicsScene class
                self.view.polyf.setFlag(QtGui.QGraphicsItem.ItemIsMovable , False)

        else:
                self.view.polyrotate = 0 
                self.view.degrees = 0
                self.view.polyf.setFlag(QtGui.QGraphicsItem.ItemIsMovable)

class Example(QtGui.QGraphicsView):
    def mousePressEvent(self , e):
        super(Example , self).mousePressEvent(e)
        self.x = e.x()
        self.y = e.y()
        if self.polyrotate == 1:
            self.Rotate()

    def Rotate(self):

        self.pverticesx = []
        self.pverticesy = []
        distances = []
        for i in range(4):
            self.pverticesx.append(self.polyf.mapToScene(self.polyf.polygon()[i]).x())
            self.pverticesy.append(self.polyf.mapToScene(self.polyf.polygon()[i]).y())

        x1 = self.x
        y1 = self.y      

        for i in range(4):
             distance = math.hypot(self.pverticesx[i] - x1 , self.pverticesy[i] - y1)
             distances.append(distance)
        midpointx = (self.pverticesx[0] +  self.pverticesx[2]) / 2
        midpointy = (self.pverticesy[0] +  self.pverticesy[2]) / 2
        index = distances.index(min(distances))          
        pointx = self.pverticesx[index]                
        pointy = self.pverticesy[index]
        vector1 = [x1 - midpointx , y1 - midpointy]
        vector2 = [pointx - midpointx , pointy - midpointy]
        num = 0

        for i in [0 , 1]:
            num = num + (vector1[i] * vector2[i])  
        den = math.sqrt(sum(map(lambda x : x * x , vector1))) *  math.sqrt(sum(map(lambda x : x * x , vector2)))

        degree = math.degrees(math.acos(num / den))
        self.degrees = degree + self.degrees
        if self.degrees > 360:
            rotation = self.degrees / 360
            self.degrees = self.degrees - (rotation * 360)

        self.polyf.setTransformOriginPoint(midpointx , midpointy)
        self.polyf.setRotation(self.degrees)

这里有一个更详细的链接到我的代码。RotateApp。提前谢谢大家。

2 个回答

1

我对PyQt不是很熟悉,但在旋转的时候,大多数的API都是围绕点(0,0)进行旋转的,所以正确的做法是:
1 - 先把多边形移动到(0,0)这个点
2 - 然后对多边形进行旋转
3 - 最后再把多边形移动回原来的位置

希望这能帮到你,

祝好。

2

我自己找到了问题的答案。在旋转之前,midpointx 和 midpointy 是在场景坐标系中的。所以我需要把它们转换回 QGraphicsItem 的坐标系统。在调用 self.setRotation() 之前加上这一行代码就可以解决这个问题。

self.polyf.setTransformOriginPoint(self.polyf.mapFromScene(QtCore.QPointF(midpointx , midpointy)))

现在我的多边形不会随机移动了。

撰写回答