我有一个代表我正在制作的图表编辑器的简单示例。
在图表中我有“父”对象,可以有孩子,孩子们应该创建和维护与父母联系的行。
在以下示例中,黑色方块是父级,红色三角形是子级。
孩子与父母一起创建一条线,但是当我移动孩子时,线不会重新对齐。理想情况下,我会扩展mouseMoveEvent函数来执行它本身的任何操作以及行重绘功能。
让孩子重新划线的最佳方法是什么?
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class ParentNode(QGraphicsRectItem):
def __init__(self, diagramScene, parent=None, h=60, w=60):
QGraphicsItemGroup.__init__(self, parent)
self.scene = diagramScene
self.h = h
self.w = w
self.setPen(QPen(Qt.black, 2))
self.setBrush(QBrush(Qt.black))
self.setFlags(self.ItemIsSelectable | self.ItemIsMovable)
self.setCursor(QCursor(Qt.PointingHandCursor))
square = QGraphicsPolygonItem()
square.setPolygon(QPolygonF([QPointF(0, 0), QPointF(20, 0), QPointF(20, 20), QPointF(0, 20)]))
self.setRect(0.0, 0.0, self.w, self.h)
class ChildNode(QGraphicsItemGroup):
def __init__(self, parent):
QGraphicsItemGroup.__init__(self, parent)
self.parent = parent
self.setFlags(self.ItemIsSelectable | self.ItemIsMovable)
triangle = QGraphicsPolygonItem()
triangle.setPolygon(QPolygonF([QPointF(0, 0), QPointF(20, 0), QPointF(10, 20)]))
triangle.setPen(QPen(Qt.red, 2))
self.addToGroup(triangle)
self.setPos(180, 180)
# define line at first
self.line = self.parent.scene.addLine(self.x() + 10,
self.y() + 0,
self.parent.x() + self.parent.w / 2,
self.parent.y() + self.parent.h)
if __name__ == '__main__':
app = QApplication(sys.argv)
scene = QGraphicsScene()
n1 = ParentNode(scene)
scene.addItem(n1)
n2 = ChildNode(n1)
scene.addItem(n2)
view = QGraphicsView(scene)
view.show()
view.resize(600, 400)
sys.exit(app.exec_())
PS:这个例子是一个更复杂的程序的表示,所以我需要尽可能少地改变类继承。
答案 0 :(得分:2)
执行此操作的最简单方法是子类化依赖项并重新实现其itemChange方法,以便监视位置更改。下面是重写你的脚本:
import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class LineUpdateMixin(object):
def __init__(self, parent):
super(LineUpdateMixin, self).__init__(parent)
self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges)
def itemChange(self, change, value):
if change == QGraphicsItem.ItemScenePositionHasChanged:
self.parentItem().updateLine(value)
return super(LineUpdateMixin, self).itemChange(change, value)
class Triangle(LineUpdateMixin, QGraphicsPolygonItem): pass
class ParentNode(QGraphicsRectItem):
def __init__(self, diagramScene, parent=None, h=60, w=60):
super(ParentNode, self).__init__(parent)
self.setPen(QPen(Qt.black, 2))
self.setBrush(QBrush(Qt.black))
self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable)
self.setCursor(QCursor(Qt.PointingHandCursor))
square = QGraphicsPolygonItem()
square.setPolygon(QPolygonF([QPointF(0, 0), QPointF(20, 0), QPointF(20, 20), QPointF(0, 20)]))
self.setRect(0.0, 0.0, w, h)
class ChildNode(QGraphicsItemGroup):
def __init__(self, parent):
super(ChildNode, self).__init__(parent)
self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable)
self.line = QGraphicsLineItem()
parent.scene().addItem(self.line)
self.updateLine(self.pos())
triangle = Triangle(self)
triangle.setPolygon(QPolygonF([QPointF(0, 0), QPointF(20, 0), QPointF(10, 20)]))
triangle.setPen(QPen(Qt.red, 2))
self.addToGroup(triangle)
self.setPos(180, 180)
def updateLine(self, pos):
parent = self.parentItem()
rect = parent.rect()
self.line.setLine(
pos.x() + 10, pos.y() + 0,
parent.x() + rect.width() / 2,
parent.y() + rect.height(),
)
if __name__ == '__main__':
app = QApplication(sys.argv)
scene = QGraphicsScene()
n1 = ParentNode(scene)
scene.addItem(n1)
n2 = ChildNode(n1)
view = QGraphicsView(scene)
view.setGeometry(600, 100, 600, 400)
view.show()
sys.exit(app.exec_())