物体移动时重绘线条

时间:2016-11-13 12:31:47

标签: python-3.x pyqt5

我有一个代表我正在制作的图表编辑器的简单示例。

在图表中我有“父”对象,可以有孩子,孩子们应该创建和维护与父母联系的行。

在以下示例中,黑色方块是父级,红色三角形是子级。

孩子与父母一起创建一条线,但是当我移动孩子时,线不会重新对齐。理想情况下,我会扩展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_())

enter image description here

PS:这个例子是一个更复杂的程序的表示,所以我需要尽可能少地改变类继承。

1 个答案:

答案 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_())