PyQT5 setRect перемещает исходную точку в QGraphicsScene

Каждый раз, когда я пытаюсь переместить прямоугольник в сцене, кажется, что исходная точка прямоугольника меняется на то место, где находился прямоугольник до обновления местоположения.

Итак, если я создаю прямоугольник в точке (0,0) и перемещаю его с помощью rect.setRect (x, y), то возвращение позиции даст (0,0) вместо (x, y).

Если вы переместите его в QGraphicsScene с помощью мыши, он вернет правильные (x, y).

Код, который я использую для создания прямоугольника, следующий:

class placeableObject:
    def __init__(self, index, scene, QPen, QBrush, width=100, height=100):
        """Parent class for placeable objects"""
        self.width = float(width)
        self.height = float(height)
        self.index = index

        self.rect = scene.addRect(0, 0, int(width), int(height), QPen, QBrush)
        self.rect.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)

Чтобы переместить этот прямоугольник, у меня есть следующая встроенная функция и функция для возврата позиции:

def getPos(self):
    """Returns a list with the x,y position of the object in the scene"""
    return [self.rect.scenePos().x(), self.rect.scenePos().y()]

def move(self, x, y):
    """Moves the object in the editor view to coordinatex x,y"""
    self.rect.setRect(x, y, self.width, self.height)

person cooldanietje    schedule 29.09.2020    source источник


Ответы (2)


Вы забываете важный аспект графических элементов: их [сцена] положение не всегда является верхним левым углом объекта, который фактически отображается пользователю. Это очевидно при добавлении элементов с использованием scene.add*() (это уже объяснялось в этот вопрос).
Как поясняется в документации :

Обратите внимание, что геометрия элемента указывается в координатах элемента, а его положение инициализируется значением (0, 0). Например, если добавлен QRect (50, 50, 100, 100), его верхний левый угол будет в (50, 50) относительно начала координат в системе координат элемента.

Положение элемента не является положением прямоугольника, поэтому, когда вы используете setRect, вы не перемещаете элемент, а устанавливаете новый прямоугольник в указанном положении, оставляя элемент в (0, 0) координаты своей системы; обратите внимание, что это также означает, что если у элемента нет родителя, scenePos() будет таким же, как pos(), в противном случае он будет относиться к родительскому элементу.

Если вы хотите узнать фактическое положение верхнего левого угла прямоугольника, вы можете использовать одно из следующих действий:

  • item.sceneBoundingRect().topLeft()
  • item.scenePos() + item.rect().topLeft()

Если вы всегда добавляете прямоугольник в (0, 0), вы можете просто использовать setPos(), но если вам нужно вычислить положение на основе текущего фактического положения прямоугольника, вы должны использовать одну из функций, указанных выше.

Обратите внимание, что прямоугольники также могут иметь отрицательные размеры, поэтому, если вам нужен верхний левый угол видимого прямоугольника, вам необходимо нормализовать его:

    item.scenePos() + item.rect().normalized().topLeft()
person musicamante    schedule 29.09.2020
comment
В этом есть большой смысл, спасибо за подробный ответ, это очень помогает! - person cooldanietje; 29.09.2020

Кажется, я разобрался.

Я изменил функцию перемещения на следующую:

def move(self, x, y):
    """Moves the object in the editor view to coordinatex x,y"""
    self.rect.setPos(x, y)

Это возвращает мне правильные позиции в сцене! Спасибо, в любом случае :)

person cooldanietje    schedule 29.09.2020