QGraphicsItem 交互式调整矩形大小
QGraphicsItem interactive resize for rectangles
我正在制作一个用户可以在场景中绘制矩形、圆形和多边形的应用程序。然后可以选择、删除、移动这些项目等。下面的代码显示了我为实现这一目标所做的工作:
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
我的椭圆有完全相同的代码。当我调整椭圆 'negatively' 的大小时,即在左上点上方,它会相应地调整大小。然而,矩形只是消失了,它可能会留下一小块红色痕迹,但它并没有按照预期的方式绘制。为什么这与矩形不同?我该如何解决?
我在堆栈溢出上看到的大多数解决方案似乎都有些矫枉过正,而且代码太多,只适合一个小的实现。
期望setRect()
的矩形必须是有效的,例如QRectF(0, 0, 100, 100)
是有效的,但是QRectF(100, 100, 0, 0)
是无效的,所以解决方法是用[=14使它有效=]
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
的情况下标准化矩形,因此您看不到那个问题。
我正在制作一个用户可以在场景中绘制矩形、圆形和多边形的应用程序。然后可以选择、删除、移动这些项目等。下面的代码显示了我为实现这一目标所做的工作:
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
我的椭圆有完全相同的代码。当我调整椭圆 'negatively' 的大小时,即在左上点上方,它会相应地调整大小。然而,矩形只是消失了,它可能会留下一小块红色痕迹,但它并没有按照预期的方式绘制。为什么这与矩形不同?我该如何解决?
我在堆栈溢出上看到的大多数解决方案似乎都有些矫枉过正,而且代码太多,只适合一个小的实现。
期望setRect()
的矩形必须是有效的,例如QRectF(0, 0, 100, 100)
是有效的,但是QRectF(100, 100, 0, 0)
是无效的,所以解决方法是用[=14使它有效=]
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
的情况下标准化矩形,因此您看不到那个问题。