PySide/PyQt4 绘制节点和连接

PySide/PyQt4 draw nodes and connections

正在尝试创建节点并将它们相互连接。我堆在 setElementPositionAt 上。错误是: AttributeError: 'PySide.QtGui.QPainterPath' object has no attribute 'updateElement' 我在这里找到了工作代码:How can I draw nodes and edges in PyQT? 但无法使其适应我的小部件。 我做错了什么? 这是代码:

from PySide.QtCore import *
from PySide.QtGui import *

rad = 5


class WindowClass(QMainWindow):
    def __init__(self):
        super(WindowClass, self).__init__()
        self.view = ViewClass()
        self.setCentralWidget(self.view)


class ViewClass(QGraphicsView):
    def __init__(self):
        super(ViewClass, self).__init__()

        self.setDragMode(QGraphicsView.RubberBandDrag)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.s = SceneClass()
        self.setScene(self.s)
        self.setRenderHint(QPainter.Antialiasing)


class SceneClass(QGraphicsScene):
    def __init__(self, id=None):
        super(SceneClass, self).__init__()
        self.setSceneRect(-1000, -1000, 2000, 2000)
        self.grid = 30

        self.p = QPainterPath()
        self.it = None
        self.node = None

    def drawBackground(self, painter, rect):
        if False:
            painter = QPainter()
            rect = QRect()

        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 mousePressEvent(self, event):
        if event.button() == Qt.RightButton:
            self.p.moveTo(0, 0)
            self.p.lineTo(200, 100)
            self.it = Path(self.p,None)
            self.addItem(self.it)
            for i in xrange(2):
                self.node = Node(self, i, QPointF(self.p.elementAt(i)))
                self.node.setPos(QPointF(self.p.elementAt(i)))
                self.addItem(self.node)

        super(SceneClass, self).mousePressEvent(event)


class Path(QGraphicsPathItem):
    def __init__(self, path, scene):
        super(Path, self).__init__(path)
        self.pth = path

        self.scn = SceneClass(self.setPen(QPen(Qt.red, 1.75)))

    def updateElement(self, index, pos):
        print pos
        self.pth.setElementPositionAt(index, pos.x(), pos.y())
        self.pth.setPath(self)


class Node(QGraphicsEllipseItem):
    def __init__(self, path, index, pos):
        super(Node, self).__init__(-rad, -rad, 2*rad, 2*rad)

        self.pos = pos
        self.rad = rad
        self.path = QPainterPath()
        self.index = index
        self.setZValue(1)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges)
        self.setBrush(Qt.green)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemPositionChange:
            self.path.updateElement(self.index, value)
        return QGraphicsEllipseItem.itemChange(self, change, value)

if __name__ == '__main__':
    app = QApplication([])
    wd = WindowClass()
    wd.show()
    app.exec_()

您已对作为参考的基础 classes 进行了更改,因此如果您不理解代码,出现错误是正常的。

当您调用 updateElement 方法时,您必须从路径 class 的实例执行它,而不是 class QPaintePath 的实例,我已经放置您最初作为参考使用的作者的相同代码,我已将其添加到您的图形部分。

class WindowClass(QMainWindow):
    def __init__(self):
        super(WindowClass, self).__init__()
        self.view = ViewClass()
        self.setCentralWidget(self.view)


class ViewClass(QGraphicsView):
    def __init__(self):
        super(ViewClass, self).__init__()

        self.setDragMode(QGraphicsView.RubberBandDrag)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.s = SceneClass()
        self.setScene(self.s)
        self.setRenderHint(QPainter.Antialiasing)


class SceneClass(QGraphicsScene):
    def __init__(self, id=None):
        super(SceneClass, self).__init__()
        self.setSceneRect(-1000, -1000, 2000, 2000)
        self.grid = 30
        self.it = None
        self.node = None

    def drawBackground(self, painter, rect):
        if False:
            painter = QPainter()
            rect = QRect()

        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 mousePressEvent(self, event):
        if event.button() == Qt.RightButton:
            path = QPainterPath()
            path.moveTo(0, 0)
            path.lineTo(200, 100)
            self.addItem(Path(path, self))
        super(SceneClass, self).mousePressEvent(event)

class Node(QGraphicsEllipseItem):
    def __init__(self, path, index):
        super(Node, self).__init__(-rad, -rad, 2*rad, 2*rad)

        self.rad = rad
        self.path = path
        self.index = index

        self.setZValue(1)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges)
        self.setBrush(Qt.green)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemPositionChange:
            self.path.updateElement(self.index, value)
        return QGraphicsEllipseItem.itemChange(self, change, value)


class Path(QGraphicsPathItem):
    def __init__(self, path, scene):
        super(Path, self).__init__(path)
        for i in range(path.elementCount()):
            node = Node(self, i)
            node.setPos(QPointF(path.elementAt(i)))
            scene.addItem(node)
        self.setPen(QPen(Qt.red, 1.75))        

    def updateElement(self, index, pos):
        path = self.path()
        path.setElementPositionAt(index, pos.x(), pos.y())
        self.setPath(path)