Как я могу нарисовать узлы и ребра в PyQT? - PullRequest
10 голосов
/ 31 января 2010

В PyQT, как я могу построить маленькие «Узлы» в заданных точках и соединить их с ребрами? Все учебники по PyQT, которые я нахожу, - «Нарисуй кнопку! Нарисуй флажок!»

Огромное спасибо заранее

Ответы [ 2 ]

3 голосов
/ 09 декабря 2014

Было трудно найти хорошее объяснение этому (уже к концу 2014 года), и, поскольку этот вопрос точно задает, что я искал, я выложу транскрипцию (с C ++ на Python) из того, что я нашел в этом посте .

Код ниже, и вот обоснование:

  1. QGrahpicsItem, QPainterPath и QPainterPath.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_()
3 голосов
/ 01 февраля 2010

Если вы хотите иметь возможность взаимодействовать с объектами, отображаемыми на графике, вам будет лучше использовать QGraphicsScene . Он обрабатывает масштабирование и панорамирование и может содержать другие QGraphicsItem объекты, которые могут обрабатывать свои собственные взаимодействия.

Его очень просто использовать, но при этом возникают некоторые накладные расходы, особенно если вы планируете создавать тысячи объектов.

Вы можете найти учебник по PyQt здесь . Это и документация по API должны помочь вам начать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...