Это происходит по двум причинам:
- Поскольку вы делаете элемент подвижным, вы можете перемещать его свободно, где угодно по вашему желанию.
- Когда прямоугольник сцены меньше, чем тот, который отображается в представлении, представление пытается гарантировать, что весь прямоугольник сцены остается видимым, возможно, путем прокрутки его содержимого.
Обратите внимание, что, если явно не установлено с помощью setSceneRect()
(на сцене или в представлении результаты могут отличаться), Qt автоматически устанавливает прямоугольник сцены неявно на больший QRect, содержащий все видимые графические элементы.
Существует по крайней мере два возможных решения вашей проблемы, которые выбор одного из них зависит от того, что вам нужно, и вы также можете решить использовать оба из них.
Явно установить sceneRect
Вы можете установить sceneRect на определенный прямоугольник c, элемент или все существующие элементы. Обратите внимание: хотя в вашем случае это не сильно изменится, если вы установите прямоугольник для сцены или вида, в более сложных случаях (например, несколько видов, показывающих одну и ту же сцену) результат может отличаться.
# on the view
self.setSceneRect(self.scene_r.itemsBoundingRect())
# alternativaly, on the scene
self.setSceneRect(self.itemsBoundingRect())
Ограничьте область, в которой элемент может быть перемещен
В этом случае вы можете перехватить itemChange ItemPositionChange
(обратите внимание, что должен быть установлен флаг ItemSendsGeometryChanges
) и возвращает скорректированное значение до того, как оно действительно применяется:
class RecItem(QGraphicsRectItem):
def __init__(self, *args):
super().__init__(*args)
self.setFlags(self.ItemSendsGeometryChanges)
def itemChange(self, change, value):
if change == self.ItemPositionChange:
sceneRect = self.scene().sceneRect()
newGeometry = self.boundingRect().translated(value)
# the item pen must be taken into account
halfPen = self.pen().width() / 2
if value.x() < sceneRect.x():
value.setX(sceneRect.x() + halfPen)
if value.y() < sceneRect.y():
value.setY(sceneRect.y() + halfPen)
if newGeometry.right() + halfPen > sceneRect.right():
value.setX(sceneRect.right() - newGeometry.width())
if newGeometry.bottom() + halfPen > sceneRect.bottom():
value.setY(sceneRect.bottom() - newGeometry.height())
return value
return super().itemChange(change, value)