QGraphicsItem交互式调整矩形大小

时间:2018-10-22 09:27:07

标签: python pyqt qgraphicsrectitem

我正在开发一个用户可以在场景上绘制矩形,圆形和多边形的应用程序。然后可以选择,删除,移动这些项目,等等。下面的代码显示了我为实现这一目的所做的事情:

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 :(得分:1)

期望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的情况下将矩形归一化,因此您不会看到该问题。