I had an annoying problem with my PyQt app, but I fixed it. I present it here so other newbies can avoid making the same mistake.

My PyQt app had a class derived from QGraphicsScene. The scene adds about a hundred QPixMaps to itself.

Trouble was, when the program exited, I got about a hundred of the following error messages:

QObject::startTimer: QTimer can only be used with threads started with QThread

As a matter of fact, there were the same number of error messages as the number of QPixMaps.

After reading the PyQt API, I found the solution. The API stated:
QGraphicsScene.__init__ (self, QObject parent = None)
The parent argument, if not None, causes self to be owned by Qt instead of PyQt.
Yes, when I checked, I discovered that I had not passed a parent argument to the init function of my QGraphicsScene sub-class. When I passed "self", the problem vanished.

Why did this happen? A note on the PyQt forum said the problem sometimes happens when Python's garbage collection deletes items in the wrong order.

This code fragment illustrates the problem:

Qt Code:
  1. from PyQt4 import QtCore, QtGui
  2.  
  3. class ModelHexMap(QtGui.QGraphicsScene):
  4.  
  5. def __init__(self, tilePath, mapPath, parent=None):
  6. QtGui.QGraphicsScene.__init__(self, parent)
  7. self.commonInit(tilePath, mapPath)
  8.  
  9. def commonInit(tilePath, mapPath):
  10. # make calls to self.addPixmap()
  11.  
  12. class MyForm(QtGui.QMainWindow):
  13.  
  14. def __init__(self, parent=None):
  15. QtGui.QMainWindow.__init__(self, parent)
  16.  
  17. # the following causes the error
  18. self.ModelHexMap = ModelHexMap("game.til", "game.map")
  19. # this is the correct way
  20. self.ModelHexMap = ModelHexMap("game.til", "game.map", self)
  21.  
  22. if __name__ == "__main__":
  23. app = QtGui.QApplication(sys.argv)
  24. myapp = MyForm()
  25. myapp.show()
  26. sys.exit(app.exec_())
To copy to clipboard, switch view to plain text mode