让我们首先将问题分成较小的问题,然后再次将所有内容组合起来。我在此解决方案中使用 PyQt5。
1. 旋转一个QGraphicsItem
为此,您需要使用以下命令设置旋转角度(以度为单位)setRotation
在该项目上。旋转将围绕由指定的点进行setTransformOriginPoint
。通常,一个会占据形状的中心。如果不指定该点,通常会采用形状的左上角。
2. 拖动一个QGraphicsItem
出于性能原因,QGraphicsItem 不可移动,并且不会将位置更改发送到事件框架。通过设置适当的标志QtWidgets.QGraphicsItem.ItemIsMovable | QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges
你可以改变这一点。此外QGraphicsItem
不继承自QObject
,因此为了使用信号,我通常有一个继承自 QObject 的附加对象。
3.绘制一个手柄项并确定要旋转的旋转角度
在下面的示例中,我有一个非常小的矩形作为句柄,您当然可以使用您喜欢的任何 QGraphicsItem。我的方法make_GraphicsItem_draggable
接受任何 QGraphicsItem 派生类并使其可拖动。为了确定给定可拖动手柄项目的当前位置和要旋转的项目的变换原点的旋转角度,请使用math.atan2
以及差异x
and y
这些位置的坐标。
Example
import math
from PyQt5 import QtCore, QtWidgets
class DraggableGraphicsItemSignaller(QtCore.QObject):
positionChanged = QtCore.pyqtSignal(QtCore.QPointF)
def __init__(self):
super().__init__()
def make_GraphicsItem_draggable(parent):
class DraggableGraphicsItem(parent):
def __init__(self, *args, **kwargs):
"""
By default QGraphicsItems are not movable and also do not emit signals when the position is changed for
performance reasons. We need to turn this on.
"""
parent.__init__(self, *args, **kwargs)
self.parent = parent
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable | QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges)
self.signaller = DraggableGraphicsItemSignaller()
def itemChange(self, change, value):
if change == QtWidgets.QGraphicsItem.ItemPositionChange:
self.signaller.positionChanged.emit(value)
return parent.itemChange(self, change, value)
return DraggableGraphicsItem
def rotate_item(position):
item_position = item.transformOriginPoint()
angle = math.atan2(item_position.y() - position.y(), item_position.x() - position.x()) / math.pi * 180 - 45 # -45 because handle item is at upper left border, adjust to your needs
print(angle)
item.setRotation(angle)
DraggableRectItem = make_GraphicsItem_draggable(QtWidgets.QGraphicsRectItem)
app = QtWidgets.QApplication([])
scene = QtWidgets.QGraphicsScene()
item = scene.addRect(0, 0, 100, 100)
item.setTransformOriginPoint(50, 50)
handle_item = DraggableRectItem()
handle_item.signaller.positionChanged.connect(rotate_item)
handle_item.setRect(-40, -40, 20, 20)
scene.addItem(handle_item)
view = QtWidgets.QGraphicsView(scene)
view.setFixedSize(300, 200)
view.show()
app.exec_()
开始(项目 = 大矩形,手柄 = 小矩形)
拖动手柄后旋转(小矩形)
缺少一件事:手柄到项目位置没有固定距离(即,您可以将其拖得更远或更近,而不是绕圈移动)。虽然这不会改变旋转角度,但看起来并不完美。但这里涵盖了要点,应该能让您走上正确的道路。