PySide Node Graph connect items

萝らか妹 提交于 2019-11-28 11:23:17

问题


The purpose of this code is node graph kind of UI. Double click creates rectangles and right click connects them with line. If you move on of the rectangle the corresponding end of line moves with it. The problem is that the line moves only with first two rectangles. If you create another pair of rectangles and connect them with line it stops moving. I have started to learn PySide/PyQt recently so maybe I don't understand all code.

Here is the code: https://github.com/cyberiRex/irex/blob/master/nodeGraph


回答1:


The Code that generates this error is the following one:

self.selectedItems()[0].linkToItem = item
self.selectedItems()[1].linkToItem = item

Let's say that one node is already connected to another by a link, when another link is added, the previous link is removed, which is why they are disconnected.

The logic like this will continue generating similar errors so the solution I propose is a new solution logic, for this I base on the following example Elastic Nodes Example. From what you can take as a basis to understand the logic of my solution, obviously I have made some variants to meet your requirements.

In a first part I have replaced the base classes to QGraphicsRectItem and QGraphicsLineItem to reduce implementation. The logic is based on giving each Edge 2 Node to which they connect so that when it is updated take as reference to the nodes. in addition each node stores a list of the edges so that it executes the update every time the node is moved. The following code implements the above:

class SceneClass(QGraphicsScene):
    grid = 30

    def __init__(self, parent=None):
        QGraphicsScene.__init__(self, QRectF(-1000, -1000, 2000, 2000), parent)

    def drawBackground(self, painter, rect):
        painter.fillRect(rect, QColor(30, 30, 30))
        left = int(rect.left()) - int((rect.left()) % self.grid)
        top = int(rect.top()) - int((rect.top()) % self.grid)
        right = int(rect.right())
        bottom = int(rect.bottom())
        lines = []
        for x in range(left, right, self.grid):
            lines.append(QLine(x, top, x, bottom))
        for y in range(top, bottom, self.grid):
            lines.append(QLine(left, y, right, y))
        painter.setPen(QPen(QColor(50, 50, 50)))
        painter.drawLines(lines)

    def mouseDoubleClickEvent(self, event):
        node = Node()
        self.addItem(node)
        node.setPos(event.scenePos())
        QGraphicsScene.mouseMoveEvent(self, event)

    def mousePressEvent(self, event):
        if event.button() == Qt.RightButton:
            if len(self.selectedItems()) == 2:
                edge = Edge(self.selectedItems()[0], self.selectedItems()[1])
                self.addItem(edge)
        QGraphicsScene.mousePressEvent(self, event)


class Node(QGraphicsRectItem):
    def __init__(self, rect=QRectF(-75, -15, 150, 30), parent=None):
        QGraphicsRectItem.__init__(self, rect, parent)
        self.edges = []
        self.setZValue(1)
        self.setBrush(Qt.darkGray)
        self.setFlags(QGraphicsItem.ItemIsMovable |
                      QGraphicsItem.ItemIsSelectable |
                      QGraphicsItem.ItemSendsGeometryChanges)

    def addEdge(self, edge):
        self.edges.append(edge)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSelectedChange:
            self.setBrush(Qt.green if value else Qt.darkGray)

        if change == QGraphicsItem.ItemPositionHasChanged:
            for edge in self.edges:
                edge.adjust()

        return QGraphicsItem.itemChange(self, change, value)


class Edge(QGraphicsLineItem):
    def __init__(self, source, dest, parent=None):
        QGraphicsLineItem.__init__(self, parent)
        self.source = source
        self.dest = dest
        self.source.addEdge(self)
        self.dest.addEdge(self)
        self.setPen(QPen(Qt.red, 1.75))
        self.adjust()

    def adjust(self):
        self.prepareGeometryChange()
        self.setLine(QLineF(self.dest.pos(), self.source.pos()))

Obtaining what is shown in the following image:

The complete example can be found in the following link



来源:https://stackoverflow.com/questions/46142167/pyside-node-graph-connect-items

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!