Hi,
I'm currently working on a PyQt4 application, part of which is a basic graph widget. The widget's purpose is to accept data via a slot, and plot the points. The way it currently works is by storing the incoming data in a list, and a QTimer triggers a method to plot the pending data every x milliseconds.

However, I've noticed that when the widget is bigger than a certain width (~ 700 px on my PC) and the timer has a short enough interval (~ 30 ms on my PC, but even as much as 200 ms on another machine), the left part of the image vary rarely updates. It seems very odd, as the right section of the graph works great.

Originally I had thought that it could be that the next graph was starting to be plotted before the previous one had finished, but I made use of a QMutex, only plotting if it was unlocked, and the issue still occurs.

I'm pretty sure the issue is in the modifying of the QPixmap rather than the paintEvent, which simply copies the pixmap to the widget.

If anyone has any ideas of what could be the problem, they would be very much appreciated.

The method which actually plots the points onto the QPixmap:
Qt Code:
  1. def _plotPendingDataPoints(self):
  2. pm=self.graphPixmap
  3. penw=self._penWidth
  4. points=self._pendingPoints
  5.  
  6. # Return if nothing to plot
  7. if (len(points)==0): return
  8.  
  9. # Wait for lock on the list
  10. _ml=QtCore.QMutexLocker(self._pendingPointsMutex)
  11.  
  12. # Plot only if we can lock the graph mutex
  13. if (not(self._plotPointsMutex.tryLock())):
  14. return
  15.  
  16. # Amount of pixels to scroll
  17. scroll=penw*len(points)
  18.  
  19. # The first point is not plotted now, so don't shift the graph for it
  20. if (self.firstPoint()):
  21. scroll-=1
  22.  
  23. p=QtGui.QPainter(pm)
  24.  
  25. p.setBrush(QtGui.QBrush(QtGui.QColor("white")))
  26. p.setPen(QtCore.Qt.NoPen)
  27.  
  28. # Scroll graph and fill in new area
  29. pm.scroll(0-scroll, 0, scroll, 0, pm.width()-scroll, pm.height())
  30. p.drawRect(pm.width()-scroll, 0, scroll, pm.height())
  31.  
  32.  
  33. # Turn on antialiasing
  34. p.setRenderHint(QtGui.QPainter.Antialiasing)
  35.  
  36. # Set up pen for drawing lines
  37. pen = QtGui.QPen(QtGui.QColor("black"))
  38. pen.setWidth(penw)
  39. p.setPen(pen)
  40.  
  41. offset=scroll
  42. for point in points:
  43. yValNew = self.graphHeight - (self.scalePoint(point))
  44.  
  45. # Skip first point
  46. if (not(self.firstPoint())):
  47. p.drawLine(pm.width()-offset-penw, self.yVal, pm.width()-offset, yValNew)
  48.  
  49. self.yVal = yValNew
  50. offset-=penw
  51.  
  52.  
  53. # Queue update
  54. self.update()
  55.  
  56. # Clear pending points
  57. self._pendingPoints=[]
  58.  
  59. # Unlock the mutex
  60. self._plotPointsMutex.unlock()
To copy to clipboard, switch view to plain text mode