subprocesamiento: no es seguro usar pixmaps fuera del subproceso de la GUI

Estoy construyendo un reproductor de música que verifica el estado con SqueezePlay, que es una aplicación de controlador SqueezeBox. Para abreviar una larga historia, estoy comprobando el estado de Squeezeplay cada 5 segundos utilizando subprocesos. Si el título de la canción cambia, lo dejo actualizar las tags (Qlabel, carátulas del álbum (QPixmap), etc.) Sin embargo, cuando le pido que lo actualice a través de subprocesos, no estoy seguro de usar pixmaps fuera del hilo de la GUI .

¿Cómo puedo hacer subprocesos pero aún así establecer el QPixmap?

Código de muestra:

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

¡Muchas gracias!

Actualización: Intenté lo siguiente con Emit, pero no funciona. ¿Puede alguien echar un vistazo a lo que estoy haciendo mal?

 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) 

Todas las operaciones gráficas de Qt deben ocurrir en el hilo principal. Otros subprocesos realmente no pueden llamar operaciones gráficas Qt (incluyendo probablemente pixmaps).

Podrían emitir señales Qt al hilo principal. O simplemente (en Linux) escriba en una tubería, y haga que el hilo principal espere la entrada en esa tubería.

Por supuesto, debe definir las señales (y también las ranuras) que desee. En el código C ++, debe marcarlos con signals: (o slots: y su código C ++ debe ser procesado por el moc . No sé cuál es la contraparte de Python (quizás las habilidades de reflexión de Python podrían ser suficientes, realmente no lo sé). A continuación, debe conectar las señales a las ranuras, con una conexión en cola . No tengo idea de cómo hacer eso en Python.

Para responder a la pregunta sobre cómo emitir la señal en python:

A diferencia de C ++, cuando se emite una señal de PyQt definida por el usuario (a diferencia de una Qt), se debe omitir la firma.

Entonces, para emitir la señal, haz algo como esto:

 thread.emit(QtCore.SIGNAL('newArtworkAvailable'), icon) 

Y para conectarte a la señal, haz algo como esto:

 widget.connect(thread, QtCore.SIGNAL('newArtworkAvailable'), widget.setNewArtwork) 

Y para ser claros:

Para que esto funcione, el subproceso no gui debe emitir la señal, que luego recibe el widget correspondiente en el subproceso principal. La creación de una QImage en el subproceso no gui debería estar bien, pero nunca intente llamar a ningún método relacionado con gui fuera del subproceso principal.

NB :

He usado la syntax de señal de estilo antiguo aquí porque eso es lo que parece que estás usando. Sin embargo, es posible que desee ver el nuevo estilo de PyQt y el soporte de ranura, ya que es mucho más flexible y pythonic.

probablemente deba enviar todos sus trabajos de dibujo al hilo principal.

He intentado algo, por favor, avíseme si suena una campana, he hecho algo similar para el mío (pero estoy lejos de python por un tiempo, así que es posible que también haya cometido errores, si es así, lo siento).

 class MyThread(QThread, ui): def __init__(self, ui): super(MyThread, self).__init__(self) self.ui = ui def run(self): coverArt = self.ui.getArtwork() coverPixMap = QtGui.QPixmap() coverPixmap.convertFromImage(QtGui.QIcon(coverArt)) icon = QtGui.QImage(coverPixMap) self.ui.item.setIcon(icon) // set icon self.ui.singerLabel.setText("Singer") // update label # your gui class class YourInterface(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) myThread = MyThread(self) self.myButton.clicked.connect(myThread.run) # all other stuff # #