PySide Node Graph connect items

后端 未结 1 783
滥情空心
滥情空心 2020-12-04 01:14

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

相关标签:
1条回答
  • 2020-12-04 01:50

    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

    0 讨论(0)
提交回复
热议问题