2012-04-15 3 views
1

Ich arbeite an einer Qt-basierten Anwendung (eigentlich in PyQt, aber ich denke nicht, dass das hier relevant ist), von denen ein Teil möglicherweise einen kontinuierlichen Strom plotten von Daten auf einem Graph in Echtzeit.Qt/PyQt - häufig Zeichnen von Pixmap zu Widget, teilweise nicht korrekt zeichnen

Ich habe dies implementiert, indem ich eine von QWidget abgeleitete Klasse erstellt habe, die eingehende Daten zwischenspeichert und den Graph alle 30ms (standardmäßig) plottet. In __init__() wird ein QPixmap erzeugt, und bei jedem Tick eines QTimer (1) wird der Graph um die Anzahl der Pixel, die die neuen Daten aufnehmen werden, nach links verschoben, (2) ein in den Raum gemaltes Rechteck, (3) die Punkte aufgetragen, und (4) update() auf das Widget genannt, wie folgt (geschnitten):

# Amount of pixels to scroll 
    scroll=penw*len(points) 

    # The first point is not plotted now, so don't shift the graph for it 
    if (self.firstPoint()): 
     scroll-=1 

    p=QtGui.QPainter(pm) 
    # Brush setup would be here... 

    pm.scroll(0-scroll, 0, scroll, 0, pm.width()-scroll, pm.height()) 
    p.drawRect(pm.width()-scroll, 0, scroll, pm.height())   

    # pen setup etc happens here... 

    offset=scroll 

    for point in points: 
     yValNew = self.graphHeight - (self.scalePoint(point)) 

     # Skip first point 
     if (not(self.firstPoint())): 
      p.drawLine(pm.width()-offset-penw, self.yVal, pm.width()-offset, yValNew) 

     self.yVal = yValNew 
     offset-=penw 

    self.update() 

Schließlich ist die paintEvent einfach zieht das Pixmap auf das widget:

p = QtGui.QPainter(self) 
    p.drawPixmap(0, 0, self.graphPixmap) 

wie Soweit ich sehen kann, sollte dies jedoch richtig funktionieren, wenn Daten sehr schnell empfangen werden (dh der gesamte Graph wird pl otted auf jedem Tick), und das Widget ist größer als eine bestimmte Größe (ca. 700px), alles auf der linken Seite des 700px Bereich hinkt erheblich. Dies ist vielleicht am besten in diesem Video gezeigt: http://dl.dropbox.com/u/1362366/keep/Graph_bug.swf.html (das Video ist ein wenig laggy wegen der niedrigen Bildrate, aber der Effekt ist sichtbar)

Irgendwelche Ideen, was könnte dies oder die Dinge, die ich versuchen könnte?

Danke.

Antwort

0

Ich bin nicht 100% sicher, ob das das Problem ist oder nicht, aber ich dachte, ich könnte zumindest etwas beitragen.

self.update() ist ein asynchroner Aufruf, der später, wenn die Hauptereignisschleife wieder erreicht wird, zu einem Paint-Ereignis führt. Daher frage ich mich, ob Ihre Zeichnung Probleme mit dem Problem der Synchronisierung hat, wenn Sie Ihr Pixmap ändern oder es tatsächlich in paintEvent verwenden. Fast scheint das, was Sie für diesen genauen Code benötigen würden, um eine Sperre in Ihrem PaintEvent, aber das ist ziemlich ungezogen klingt.

Für einen schnellen Test, könnten Sie versuchen, die Ereignisschleife zwingen Recht zu spülen nach Ihrem Anruf zu aktualisieren, um:

self.update() 
QtGui.QApplication.processEvents() 

sicher, dass es nicht so beheben, aber es ist ein Versuch wert. unter Verwendung eine Controlled Framerate

da Sie eine „Animation“ Das könnte in der Tat eine richtige Situation repaint() und verursacht ein direktes Paint-Ereignis werden zu verwenden, tun: self.repaint()

ich eine ähnliche Frage zu Ihnen bemerkt hat, von jemandem versuchen, einen Herzmonitor in Echtzeit zu zeichnen: http://qt-project.org/forums/viewthread/10677
Vielleicht könnten Sie versuchen, Ihren Code ähnlich zu strukturieren. Anstatt das Bild in zwei Phasen zu teilen, verwendet er ein QLabel als Anzeige-Widget, setzt das Pixmap in QLabel und malt das gesamte Diagramm sofort, anstatt sich auf Aufrufe des widget.update() zu verlassen.

Verwandte Themen