QGraphicsItem интерактивное изменение размера для прямоугольников - PullRequest
0 голосов
/ 22 октября 2018

Я делаю приложение, в котором пользователь может рисовать прямоугольники, круги и многоугольники на сцене.Затем эти элементы можно выбирать, удалять, перемещать и т. Д. В приведенном ниже коде показано, что я сделал для достижения этой цели:

class Rectangle(QGraphicsRectItem):

    def __init__(self, x, y, w, h):
        super(Rectangle, self).__init__(0, 0, w, h)
        super().setPen(QPen(Qt.red, 2))
        super().setFlag(QGraphicsItem.ItemIsSelectable)
        super().setFlag(QGraphicsItem.ItemIsMovable)
        super().setFlag(QGraphicsItem.ItemIsFocusable)
        super().setFlag(QGraphicsItem.ItemSendsGeometryChanges)
        super().setFlag(QGraphicsItem.ItemSendsScenePositionChanges)
        super().setPos(QPointF(x, y))

    def mouseMoveEvent(self, e):
        x = e.pos().x()
        y = e.pos().y()
        if e.buttons() == Qt.LeftButton:
            super().mouseMoveEvent(e)
        if e.buttons() == Qt.RightButton:
            super().setRect(QRectF(0, 0, x, y))

    def itemChange(self, change, val):
        if change == QGraphicsItem.ItemPositionChange:
            return QPointF(val.x(), val.y())
        return val

Рабочий код для круга:

class Circle(QGraphicsEllipseItem):

    def __init__(self, x, y, w, h):
        super(Circle, self).__init__(0, 0, w, h)
        super().setPen(QPen(Qt.darkBlue, 2))
        super().setFlag(QGraphicsItem.ItemIsSelectable)
        super().setFlag(QGraphicsItem.ItemIsMovable)
        super().setFlag(QGraphicsItem.ItemIsFocusable)
        super().setFlag(QGraphicsItem.ItemSendsGeometryChanges)
        super().setFlag(QGraphicsItem.ItemSendsScenePositionChanges)
        super().setPos(QPointF(x - w / 2 - 4, y - h / 2 - 4))

    def mouseMoveEvent(self, e):
        x = e.pos().x()
        y = e.pos().y()
        print(x, y)
        if e.buttons() == Qt.LeftButton:
            super().mouseMoveEvent(e)
        if e.buttons() == Qt.RightButton:
            super().setRect(QRectF(0, 0, x, y))

    def itemChange(self, change, val):
        if change == QGraphicsItem.ItemPositionChange:
            return QPointF(val.x(), val.y())
        return val

У меня эллипс имеет точно такой же код.Когда я изменю размер эллипса «отрицательно», то есть выше верхней левой точки, он будет соответственно изменен.Однако прямоугольник просто исчезает, он может оставить небольшой след красного цвета, но он просто не рисует так, как должен.Почему это отличается для прямоугольника?Как я могу решить эту проблему?

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

1 Ответ

0 голосов
/ 22 октября 2018

Прямоугольник, который ожидает setRect(), должен быть действительным, например, QRectF(0, 0, 100, 100) допустим, но QRectF(100, 100, 0, 0) недействителен, поэтому решение состоит в том, чтобы сделать его действительным с normalized()

from PyQt5 import QtCore, QtGui, QtWidgets


class Rectangle(QtWidgets.QGraphicsRectItem):
    def __init__(self, x, y, w, h):
        super(Rectangle, self).__init__(0, 0, w, h)
        self.setPen(QtGui.QPen(QtCore.Qt.red, 2))
        self.setFlags(QtWidgets.QGraphicsItem.ItemIsSelectable
            | QtWidgets.QGraphicsItem.ItemIsMovable
            | QtWidgets.QGraphicsItem.ItemIsFocusable
            | QtWidgets.QGraphicsItem.ItemSendsGeometryChanges
            | QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges)
        self.setPos(QtCore.QPointF(x, y))

    def mouseMoveEvent(self, e):
        if e.buttons() & QtCore.Qt.LeftButton:
            super(Rectangle, self).mouseMoveEvent(e)
        if e.buttons() & QtCore.Qt.RightButton:
            self.setRect(QtCore.QRectF(QtCore.QPoint(), e.pos()).normalized())


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    scene = QtWidgets.QGraphicsScene()
    view = QtWidgets.QGraphicsView(scene)
    scene.addItem(Rectangle(0, 0, 100, 100))
    view.show()
    sys.exit(app.exec_())

В случае QGraphicsEllipseItem нормализует прямоугольник, поэтому вы не видите этой проблемы.

...