Изменение и получение актуальных координат QGraphicsRectItem PyQt 5
Есть реализация пользовательского класса QGraphicsRectItem, который можно перемещать по картинке для выделения области на картинке. При отрисовки в методе paint() я пытаюсь выводить координаты через self.rect(), координаты остаются такими же, которые были заданы при феромоны создании объекта. Если устанавливаем в начала координаты: scene.setSceneRect(0, 0, 680, 459), то после перемещения прямоугольника, координаты остаются такими же и self.rect() выводит (0, 0, 680, 459). Почему при перемещении объекта, его координаты остаются прежними? Как получать актуальные, обновленные координаты прямоугольника после его перемещения?
import sys
from PyQt5.QtCore import Qt, QRectF, QPointF
from PyQt5.QtGui import QBrush, QPainterPath, QPainter, QColor, QPen, QPixmap
from PyQt5.QtWidgets import (QGraphicsRectItem, QApplication, QGraphicsView,
QGraphicsScene, QGraphicsItem)
class GraphicsRectItem(QGraphicsRectItem):
handleTopLeft = 1
handleTopMiddle = 2
handleTopRight = 3
handleMiddleLeft = 4
handleMiddleRight = 5
handleBottomLeft = 6
handleBottomMiddle = 7
handleBottomRight = 8
handleSize = +8.0
handleSpace = -4.0
handleCursors = {
handleTopLeft: Qt.SizeFDiagCursor,
handleTopMiddle: Qt.SizeVerCursor,
handleTopRight: Qt.SizeBDiagCursor,
handleMiddleLeft: Qt.SizeHorCursor,
handleMiddleRight: Qt.SizeHorCursor,
handleBottomLeft: Qt.SizeBDiagCursor,
handleBottomMiddle: Qt.SizeVerCursor,
handleBottomRight: Qt.SizeFDiagCursor,
}
def __init__(self, *args):
""" Инициализируйте форму. """
super().__init__(*args)
self.handles = {}
self.handleSelected = None
self.mousePressPos = None
self.mousePressRect = None
# Если установлено значение true, этот элемент будет принимать
# события при наведении курсора.
self.setAcceptHoverEvents(True) # <---
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
self.updateHandlesPos()
def handleAt(self, point):
""" Возвращает маркер изменения размера ниже заданной точки. """
for k, v, in self.handles.items():
if v.contains(point):
return k
return None
def hoverMoveEvent(self, moveEvent):
""" Выполняется, когда мышь перемещается по фигуре (NOT PRESSED). """
if self.isSelected():
handle = self.handleAt(moveEvent.pos())
cursor = Qt.ArrowCursor if handle is None else self.handleCursors[handle]
self.setCursor(cursor)
super().hoverMoveEvent(moveEvent)
def hoverLeaveEvent(self, moveEvent):
""" Выполняется, когда мышь покидает фигуру (NOT PRESSED). """
self.setCursor(Qt.ArrowCursor)
super().hoverLeaveEvent(moveEvent)
def mousePressEvent(self, mouseEvent):
""" Выполняется при нажатии мыши на элемент. """
self.handleSelected = self.handleAt(mouseEvent.pos())
if self.handleSelected:
self.mousePressPos = mouseEvent.pos()
self.mousePressRect = self.boundingRect()
super().mousePressEvent(mouseEvent)
def mouseMoveEvent(self, mouseEvent):
""" Выполняется, когда мышь перемещается над элементом при нажатии. """
if self.handleSelected is not None:
self.interactiveResize(mouseEvent.pos())
else:
super().mouseMoveEvent(mouseEvent)
def mouseReleaseEvent(self, mouseEvent):
""" Выполняется, когда мышь освобождается от элемента. """
super().mouseReleaseEvent(mouseEvent)
self.handleSelected = None
self.mousePressPos = None
self.mousePressRect = None
self.update()
def boundingRect(self):
""" Возвращает ограничивающий прямоугольник фигуры
(включая маркеры изменения размера). """
o = self.handleSize + self.handleSpace
return self.rect().adjusted(-o, -o, o, o)
def updateHandlesPos(self):
""" Обновите текущие маркеры изменения размера
в соответствии с размером и положением фигуры. """
s = self.handleSize
b = self.boundingRect()
self.handles[self.handleTopLeft] = QRectF(b.left(), b.top(), s, s)
self.handles[self.handleTopMiddle] = QRectF(b.center().x() - s / 2, b.top(), s, s)
self.handles[self.handleTopRight] = QRectF(b.right() - s, b.top(), s, s)
self.handles[self.handleMiddleLeft] = QRectF(b.left(), b.center().y() - s / 2, s, s)
self.handles[self.handleMiddleRight] = QRectF(b.right() - s, b.center().y() - s / 2, s, s)
self.handles[self.handleBottomLeft] = QRectF(b.left(), b.bottom() - s, s, s)
self.handles[self.handleBottomMiddle] = QRectF(b.center().x() - s / 2, b.bottom() - s, s, s)
self.handles[self.handleBottomRight] = QRectF(b.right() - s, b.bottom() - s, s, s)
def interactiveResize(self, mousePos):
""" Выполните форму интерактивного изменения размера. """
offset = self.handleSize + self.handleSpace
boundingRect = self.boundingRect()
rect = self.rect()
diff = QPointF(0, 0)
self.prepareGeometryChange()
if self.handleSelected == self.handleTopLeft:
fromX = self.mousePressRect.left()
fromY = self.mousePressRect.top()
toX = fromX + mousePos.x() - self.mousePressPos.x()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setX(toX - fromX)
diff.setY(toY - fromY)
boundingRect.setLeft(toX)
boundingRect.setTop(toY)
rect.setLeft(boundingRect.left() + offset)
rect.setTop(boundingRect.top() + offset)
self.setRect(rect)
elif self.handleSelected == self.handleTopMiddle:
fromY = self.mousePressRect.top()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setY(toY - fromY)
boundingRect.setTop(toY)
rect.setTop(boundingRect.top() + offset)
self.setRect(rect)
elif self.handleSelected == self.handleTopRight:
fromX = self.mousePressRect.right()
fromY = self.mousePressRect.top()
toX = fromX + mousePos.x() - self.mousePressPos.x()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setX(toX - fromX)
diff.setY(toY - fromY)
boundingRect.setRight(toX)
boundingRect.setTop(toY)
rect.setRight(boundingRect.right() - offset)
rect.setTop(boundingRect.top() + offset)
self.setRect(rect)
elif self.handleSelected == self.handleMiddleLeft:
fromX = self.mousePressRect.left()
toX = fromX + mousePos.x() - self.mousePressPos.x()
diff.setX(toX - fromX)
boundingRect.setLeft(toX)
rect.setLeft(boundingRect.left() + offset)
self.setRect(rect)
elif self.handleSelected == self.handleMiddleRight:
print("MR")
fromX = self.mousePressRect.right()
toX = fromX + mousePos.x() - self.mousePressPos.x()
diff.setX(toX - fromX)
boundingRect.setRight(toX)
rect.setRight(boundingRect.right() - offset)
self.setRect(rect)
elif self.handleSelected == self.handleBottomLeft:
fromX = self.mousePressRect.left()
fromY = self.mousePressRect.bottom()
toX = fromX + mousePos.x() - self.mousePressPos.x()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setX(toX - fromX)
diff.setY(toY - fromY)
boundingRect.setLeft(toX)
boundingRect.setBottom(toY)
rect.setLeft(boundingRect.left() + offset)
rect.setBottom(boundingRect.bottom() - offset)
self.setRect(rect)
elif self.handleSelected == self.handleBottomMiddle:
fromY = self.mousePressRect.bottom()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setY(toY - fromY)
boundingRect.setBottom(toY)
rect.setBottom(boundingRect.bottom() - offset)
self.setRect(rect)
elif self.handleSelected == self.handleBottomRight:
fromX = self.mousePressRect.right()
fromY = self.mousePressRect.bottom()
toX = fromX + mousePos.x() - self.mousePressPos.x()
toY = fromY + mousePos.y() - self.mousePressPos.y()
diff.setX(toX - fromX)
diff.setY(toY - fromY)
boundingRect.setRight(toX)
boundingRect.setBottom(toY)
rect.setRight(boundingRect.right() - offset)
rect.setBottom(boundingRect.bottom() - offset)
self.setRect(rect)
self.updateHandlesPos()
def shape(self):
""" Возвращает форму этого элемента в виде QPainterPath в локальных координатах. """
path = QPainterPath()
path.addRect(self.rect())
if self.isSelected():
for shape in self.handles.values():
path.addEllipse(shape)
return path
def paint(self, painter, option, widget=None):
""" Нарисуйте узел в графическом представлении. """
painter.setBrush(QBrush(QColor(255, 0, 0, 100)))
painter.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
painter.drawRect(self.rect())
print(self.rect())
painter.setRenderHint(QPainter.Antialiasing)
painter.setBrush(QBrush(QColor(255, 0, 0, 255)))
painter.setPen(QPen(QColor(0, 0, 0, 255), 1.0, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
for handle, rect in self.handles.items():
if self.handleSelected is None or handle == self.handleSelected:
painter.drawEllipse(rect)
if __name__ == '__main__':
app = QApplication(sys.argv)
grview = QGraphicsView()
scene = QGraphicsScene()
scene.setSceneRect(0, 0, 680, 459)
scene.addPixmap(QPixmap('D:/_Qt/img/qt-logo.png'))
grview.setScene(scene)
item = GraphicsRectItem(0, 0, 300, 150)
scene.addItem(item)
grview.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)
grview.show()
sys.exit(app.exec_())