2010-01-31 5 views
10

In PyQT, come posso tracciare piccoli "nodi" in corrispondenza di determinati punti e collegarli con i bordi? Tutti i tutorial di PyQT che trovo sono "traccia un pulsante! Traccia un checkbox!"Come posso disegnare nodi e spigoli in PyQT?

enorme grazie in anticipo

risposta

3

Se si vuole essere in grado di interagire con gli oggetti esposti nella trama, si sarà meglio utilizzare una QGraphicsScene. Gestisce lo zoom e il panning e può contenere altri oggetti QGraphicsItem in grado di gestire le proprie interazioni.

È molto facile da usare, ma è necessario un po 'di overhead, soprattutto se si prevede di creare migliaia di oggetti.

È possibile trovare un tutorial PyQt here. Questo e i documenti API dovrebbero iniziare.

+0

non sappiamo circa il tutorial che si è collegato a. Ricevo un errore di segmentazione ogni volta che chiudo l'applicazione PyQt. – rbaleksandar

+0

Il tutorial è del 2008, quindi alcune cose potrebbero essere cambiate nel frattempo. Segfault-on-close è di solito un segno che qualcosa non va con la durata/configurazione delle classi QT di base (QApplication, QMainWindow etc). Se è possibile eseguire tutorial per la propria versione di PyQt, si dovrebbe essere in grado di incorporare gli elementi necessari per far funzionare QGraphicsScene. – drxzcl

+0

Ho risolto i miei problemi. Ma sì, la versione è vecchia. – rbaleksandar

3

È stato difficile trovare una buona spiegazione per questo (già alla fine del 2014), e poiché questa domanda richiede esattamente quello che stavo cercando, posterò una trascrizione (da C++ a Python) di ciò che ho trovato in this post.

Il codice è al di sotto, e qui è la logica:

  1. QGrahpicsItem, QPainterPath e QPainterPath.Element sono le classi che stai cercando. Nello specifico, QPainterPath implementa il tipo di funzionalità vettoriale che ci si aspetta da applicazioni come CorelDraw, Adobe Illustrator o Inkscape.
  2. L'esempio seguente beneficia del valore preesistente QGraphicsEllipseItem (per i nodi di rendering) e QGraphicsPathItem (per il rendering del percorso stesso), che eredita da QGraphicsItem.
  3. Il costruttore Path itera sopra gli elementi QPainterPath, creando Node elementi per ciascuno; Ognuno di loro, a sua volta, invia aggiornamenti all'oggetto Path genitore, che aggiorna la sua proprietà path di conseguenza.
  4. Ho trovato molto, molto più facile studiare i documenti Qt4 C++ rispetto ai documenti PyQt piuttosto meno strutturati trovati altrove. Una volta che ti sei abituato a tradurre mentalmente tra C++ e Python, i documenti stessi sono un modo efficace per imparare come usare ogni classe.

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

Questo codice mi ha aiutato molto ultimamente! Grazie! Inoltre sto provando a tracciare una funzione in classe Node - mousePressEvent/middle click per aggiungere un punto di controllo al percorso lineTo.() In modo che dal punto A> BI possa aggiungere il punto C nel mezzo .. quindi posso fare un " L "shape ... significato> A/B in alto a sinistra/a destra in basso e C in angolo ... Ma non sono sicuro se è nel modo giusto in quanto non rilevo linee di disegno rosse solo cerchi quando premo .. . qualche suggerimento su come posso farlo? Grazie! – Dariusz

+1

@Dariusz Sono sicuro che ci sia una sorta di evento o flag di "passaggio del mouse" incorporato in Qt, ma non ricordo il suo nome, neigher quale classe abbia. Vorrei iniziare a cercarlo in 'QGraphicsItem'. – heltonbiker

+1

@Dariusz, in realtà li ho trovati, sono 'hoverEnterEvent' e' hoverLeaveEvent', trovato [qui] (http://doc.qt.io/qt-4.8/qgraphicsitem.html). – heltonbiker

Problemi correlati