PySide 节点图连接项
PySide Node Graph connect items
这段代码的目的是 UI 的节点图。
双击创建矩形,右键单击将它们与线连接起来。如果您继续移动矩形,相应的线端也会随之移动。问题是这条线只随着前两个矩形移动。如果你创建另一对矩形并用线连接它们,它就会停止移动。我最近才开始学习PySide/PyQt所以可能我看不懂所有代码。
代码如下:
https://github.com/cyberiRex/irex/blob/master/nodeGraph
产生这个错误的代码如下:
self.selectedItems()[0].linkToItem = item
self.selectedItems()[1].linkToItem = item
假设一个节点已经通过 link 连接到另一个节点,当添加另一个 link 时,先前的 link 将被删除,这就是它们断开连接的原因。
这样的逻辑会继续产生类似的错误,所以我提出的解决方案是一个新的解决方案逻辑,为此我基于以下示例Elastic Nodes Example。从您可以作为理解我的解决方案逻辑的基础上,显然我已经做了一些变体来满足您的要求。
在第一部分中,我将基础 类 替换为 QGraphicsRectItem 和 QGraphicsLineItem 以减少实现。该逻辑基于为每个边缘 2 节点提供它们连接的节点,以便在更新时作为节点的参考。此外,每个节点都存储一个边列表,以便在每次移动节点时执行更新。以下代码实现了上述内容:
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()))
得到如下图所示:
完整的例子可以在下面找到link
这段代码的目的是 UI 的节点图。 双击创建矩形,右键单击将它们与线连接起来。如果您继续移动矩形,相应的线端也会随之移动。问题是这条线只随着前两个矩形移动。如果你创建另一对矩形并用线连接它们,它就会停止移动。我最近才开始学习PySide/PyQt所以可能我看不懂所有代码。
代码如下: https://github.com/cyberiRex/irex/blob/master/nodeGraph
产生这个错误的代码如下:
self.selectedItems()[0].linkToItem = item
self.selectedItems()[1].linkToItem = item
假设一个节点已经通过 link 连接到另一个节点,当添加另一个 link 时,先前的 link 将被删除,这就是它们断开连接的原因。
这样的逻辑会继续产生类似的错误,所以我提出的解决方案是一个新的解决方案逻辑,为此我基于以下示例Elastic Nodes Example。从您可以作为理解我的解决方案逻辑的基础上,显然我已经做了一些变体来满足您的要求。
在第一部分中,我将基础 类 替换为 QGraphicsRectItem 和 QGraphicsLineItem 以减少实现。该逻辑基于为每个边缘 2 节点提供它们连接的节点,以便在更新时作为节点的参考。此外,每个节点都存储一个边列表,以便在每次移动节点时执行更新。以下代码实现了上述内容:
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()))
得到如下图所示:
完整的例子可以在下面找到link