2017-08-11 2 views
0

Vous essayez de créer des nœuds et de les connecter les uns aux autres. Je suis empilé sur setElementPositionAt. L'erreur est: AttributeError: 'PySide.QtGui.QPainterPath' object has no attribute 'updateElement' J'ai trouvé le code de travail ici: How can I draw nodes and edges in PyQT? mais je ne peux pas l'adapter à mon widget. Qu'est-ce que je fais mal? Voici le code:PySide/PyQt4 dessiner des nœuds et des connexions

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_() 
+0

Que voulez-vous faire dans la méthode mousePressEvent? – eyllanesc

Répondre

2

Vous avez apporté des modifications aux classes de base que vous avez pris comme référence il est donc normal pour vous d'avoir des erreurs si vous ne comprenez pas le code. Lorsque vous appelez la méthode updateElement vous devez le faire à partir d'une instance de la classe Path, pas une instance de la classe QPaintePath, j'ai placé le même code de l'auteur que vous avez pris comme référence initialement et j'ai ajouté à votre partie graphique.

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) 

enter image description here

+0

Maintenant, il est clair où mon erreur était. Juste une question. Quelle est la variable 'change' fonctionne? Je veux dire quand exécuter 'self.path.updateElement (self.index, value)'. Si j'imprime le type de cette variable, j'obtiens une liste d'objets différents. Comment 'updateElement()' obtient de cette liste 'QPointF()', car quand il exécute 'setElementPositionAt' il a besoin d'index et' pos.x() et pos.y() ' – iRex

+0

Et une autre question: Comment être sélectionné éléments de 'SceneClass'? 'self.selectedItems()' ne fournit aucune information sur les éléments sélectionnés. – iRex

+0

Si vous consultez les documents: 'setElementPositionAt()' vous remarquerez qu'il reçoit l'index de l'élément, le coordonne en x et la coordonnée en y, QPointF n'est pas d'accord directement, mais nous pouvons l'obtenir par les fonctions x () et y() – eyllanesc