threading: It is not safe to use pixmaps outside the GUI thread

FLX picture FLX · Dec 27, 2011 · Viewed 18.9k times · Source

I'm building a music player, that checks the status with SqueezePlay, which is a SqueezeBox controller app. To cut a long story short, I'm checking the status of Squeezeplay ever 5 seconds by using threading. If the song title changes, I let it update the labels (Qlabel, album artwork (QPixmap), etc. However, when I ask it to update it via threading, I'm getting It is not safe to use pixmaps outside the GUI thread .

How can I do threading but still set the QPixmap?

Sample code:

#self.sq.getArtwork() returns variable with the image
coverArt = self.sq.getArtwork()
coverPixMap = QtGui.QPixmap()
coverPixMap.loadFromData(coverArt)
self.albumArt.setPixmap(coverPixMap)

Many thanks!

Update: I tried the following with Emit, but it doesn't work, can someone take a look what I'm doing wrong?

def setNewArtwork(self, image):
    coverPixMap = QtGui.QPixmap()
    coverPixMap.convertFromImage(image)
    icon = QtGui.QIcon(coverPixMap)
    item.setIcon(icon)

def getNewArtwork(self):
    coverArt = self.sq.getArtwork()
    icon = QtGui.QImage(coverArt)
    self.emit(QtCore.SIGNAL('setNewArtwork(QImage)'), icon)

Answer

Basile Starynkevitch picture Basile Starynkevitch · Dec 27, 2011

All graphical Qt operations should happen in the main thread. Other threads are not really allowed to call Qt graphical operations (including probably pixmaps).

They could emit Qt signals to the main thread. Or simply (on Linux) write into a pipe, and have the main thread wait for input on that pipe.

Of course, you have to define the signals (and also the slots) you want. In C++ code, you need to mark them with signals: (or slots:) and your C++ code should be processed by the moc. I don't know what is the Python counterpart (perhaps python reflection abilities might be enough, I really don't know). You then have to connect signals to slots, with a queued connection. I have no idea how to do that in Python.