【问题标题】:PySide/PyQt4 draw nodes and connectionsPySide/PyQt4 绘制节点和连接
【发布时间】:2018-01-20 10:25:27
【问题描述】:

尝试创建节点并将它们相互连接。我堆在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_()

【问题讨论】:

    标签: python pyqt pyqt4 nodes pyside


    【解决方案1】:

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

    当您调用 updateElement 方法时,您必须从 Path 类的实例而不是 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)
    

    【讨论】:

    • 现在很清楚我的错误在哪里。就一个问题。变量change 是如何工作的?我的意思是当执行self.path.updateElement(self.index, value)。如果我打印该变量的类型,我会得到一个不同对象的列表。 updateElement() 如何从该列表中获取QPointF(),因为当它执行setElementPositionAt 时,它需要索引和pos.x() and pos.y()
    • 还有一个问题:如何从SceneClass 获取所选项目? self.selectedItems() 不提供有关所选元素的任何信息。
    • 如果你查看文档:setElementPositionAt()你会注意到它接收到项目的索引,在x和y坐标,QPointF不直接同意,但我们可以得到它通过函数 x() 和 y()
    • 你什么时候使用selectedItems()
    • 在mouseMoveEvent 和mousPressEvent 中。
    猜你喜欢
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 1970-01-01
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多