【问题标题】:How can I draw nodes and edges in PyQT?如何在 PyQT 中绘制节点和边?
【发布时间】:2011-01-11 12:04:12
【问题描述】:

在 PyQT 中,如何在给定点绘制小“节点”并将它们与边缘连接?我找到的所有 PyQT 教程都是“绘制一个按钮!绘制一个复选框!”

【问题讨论】:

    标签: python graph pyqt


    【解决方案1】:

    如果您希望能够与图中显示的对象进行交互,最好使用QGraphicsScene。它处理缩放和平移,并且可以包含其他可以处理自己的交互的QGraphicsItem 对象。

    它非常易于使用,但会产生一些开销,尤其是当您计划制作数千个对象时。

    您可以找到 PyQt 教程here。这和 API 文档应该可以帮助您入门。

    【讨论】:

    • 不知道您链接到的教程。每当我关闭 PyQt 应用程序时,都会出现分段错误。
    • 本教程是从 2008 年开始的,因此在此期间可能会发生一些变化。 Segfault-on-close 通常表明您的基本 QT 类(QApplication、QMainWindow 等)的生命周期/配置有问题。如果你可以为你的 PyQt 版本运行教程,你应该能够合并必要的项目来让 QGraphicsScene 工作。
    • 我已经解决了我的问题。但是,是的,版本是旧的。
    【解决方案2】:

    很难找到一个好的解释(截至 2014 年底),因为这个问题正是我在寻找什么,我将发布一个转录(从 C++ 到 Python)我在this post 中找到的内容。

    代码如下,原因如下:

    1. QGrahpicsItemQPainterPathQPainterPath.Element 是您正在寻找的课程。具体来说,QPainterPath 实现了您在 CorelDraw、Adobe Illustrator 或 Inkscape 等应用程序中所期望的那种矢量功能。
    2. 下面的示例受益于预先存在的QGraphicsEllipseItem(用于渲染节点)和QGraphicsPathItem(用于渲染路径本身),它们继承自QGraphicsItem
    3. Path 构造函数迭代QPainterPath 元素,为每个元素创建Node 项;它们中的每一个依次向父 Path 对象发送更新,该对象相应地更新其 path 属性。
    4. 我发现学习 C++ Qt4 文档比在其他地方找到的结构不那么结构化的 PyQt 文档要容易得多。一旦您习惯了在 C++ 和 Python 之间进行心理转换,文档本身就是学习如何使用每个类的有效方法。

    #!/usr/bin/env python
    # coding: utf-8
    
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    
    rad = 5
    
    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.toPointF())
            return QGraphicsEllipseItem.itemChange(self, change, value)
    
    
    class Path(QGraphicsPathItem):
        def __init__(self, path, scene):
            super(Path, self).__init__(path)
            for i in xrange(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.setElementPositionAt(index, pos.x(), pos.y())
            self.setPath(path)
    
    
    if __name__ == "__main__":
    
        app = QApplication([])
    
        path = QPainterPath()
        path.moveTo(0,0)
        path.cubicTo(-30, 70, 35, 115, 100, 100);
        path.lineTo(200, 100);
        path.cubicTo(200, 30, 150, -35, 60, -30);
    
        scene = QGraphicsScene()
        scene.addItem(Path(path, scene))
    
        view = QGraphicsView(scene)
        view.setRenderHint(QPainter.Antialiasing)
        view.resize(600, 400)
        view.show()
        app.exec_()
    

    【讨论】:

    • 这段代码最近对我帮助很大!谢谢!另外我正在尝试在类节点中绘制一个函数 - mousePressEvent / 中键单击以将控制点添加到路径 lineTo.() 以便从点 A > BI 可以在中间添加点 C.. 所以我可以做一个“ L”形状......意思是> A / B左上/右下角和C是角落......但我不确定它是否正确,因为当我按下时我没有检测到红色画线只有圆圈...... .任何提示我该怎么做?谢谢!
    • @Dariusz 我确信 Qt 中有某种内置的“鼠标悬停”事件或标志,但我不记得它的名称,不记得哪个类有它。我会开始在QGraphicsItem 中搜索。
    • @Dariusz,其实我找到了,他们是hoverEnterEventhoverLeaveEvent,找到here
    猜你喜欢
    • 2016-05-20
    • 2012-10-03
    • 2018-08-25
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多