Pregunta

Estoy practicando hilos (Q) PyQt y haciendo un simple cliente de Twitter. Tengo dos Qthreads.

  1. principal / hilo GUI.

  2. Twitter traiga hilo -. Datos recupera de Twitter cada X minutos

Por lo tanto, cada X minutos mi hilo Twitter descarga un nuevo conjunto de cambios de estado (una lista de Python). Quiero entregar esta lista a lo largo del hilo principal / interfaz gráfica de usuario, de modo que pueda actualizar la ventana con estos estados.

Estoy asumiendo que debo utilizar el sistema de señal / ranura para transferir los "estados" lista de Python desde el hilo de Twitter, al hilo principal / GUI. Por lo tanto, mi pregunta es doble:

  1. ¿Cómo se envían los estados de la rosca Twitter?

  2. ¿Cómo los recibo en el hilo principal / GUI?

Por lo que yo puedo decir, PyQt puede enviar por defecto sólo PyQt-objetos a través de señales / ranuras. Creo que se supone que de alguna manera registrar una señal personalizada que luego puedo enviar, pero la documentación sobre este que he encontrado es muy claro para un novato como yo. Tengo un libro PyQt en orden, pero no va a llegar dentro de una semana, y yo no quiero esperar hasta entonces. : -)

Estoy usando PyQt 4.6-1 en Ubuntu

Actualización:

Este es un excert a partir del código que no funciona. En primer lugar, trato de la señal ( "newStatuses", nombre acabo de componer) a la self.update_tweet_list función en el hilo principal / GUI "conectar":

QtCore.QObject.connect(self.twit_in,
                       QtCore.SIGNAL("newStatuses (statuses)"),
                       self.update_tweet_list)

A continuación, en el hilo de Twitter, hago esto:

self.emit(SIGNAL("newStatuses (statuses)"), statuses)

Cuando esta línea se llama, me sale el siguiente mensaje:

QObject::connect: Cannot queue arguments of type 'statuses'
(Make sure 'statuses' is registered using qRegisterMetaType().)

Hice una búsqueda para qRegisterMetaType (), pero no he encontrado nada relacionado con Python que pude entender.

¿Fue útil?

Solución

A partir de este ejemplo:

http://doc.qt.digia.com/4.5/qmetatype.html

 int id = QMetaType.type("MyClass");

Se puede escribir en Python

from PyQt4 import QtCore    
id = QtCore.QMetaType.type('MyClass')

Editar

La respuesta extraído del comentario:

self.emit(SIGNAL("newStatuses(PyQt_PyObject)"), statuses)

Otros consejos

También puede hacer esto, que es mucho más Pythonic (y legible!).

# create a signal equivalent to "void someSignal(int, QWidget)"
someSignal = QtCore.pyqtSignal(int, QtGui.QWidget)

# define a slot with the same signature
@QtCore.pyqtSlot(int, QtGui.QWidget)
def someSlot(status, source):
    pass

# connect the signal to the slot
self.someSignal.connect(self.someSlot)

Consulte esta pregunta que hice un tiempo atrás. Hay un ejemplo de código que podrían ayudar a determinar lo que hay que hacer.

Lo que ha dicho sobre cómo registrar su señal me hace pensar en el código (de la pregunta antes mencionada):

class ProcessingThread(threading.Thread, QtCore.QObject):
    __pyqtSignals__ = ( "progressUpdated(str)",
                        "resultsReady(str)")

Estoy de paso cuerdas en mi ejemplo, pero usted debería ser capaz de reemplazar con str list.

Si resulta que no se puede pasar objetos mutables, que puede manejar los resultados de la manera que lo hago en mi ejemplo (es decir, establecer una variable results en el hilo, el hilo principal decir que están listos, y tienen la hilo principal "recogerlos").

Actualización:

Se obtiene el mensaje QObject::connect: Cannot queue arguments of type 'statuses' porque es necesario para definir el type del argumento que va a pasar cuando se emiten su señal. El tipo que desea pasar es no list statuses.

Cuando se conecta la señal que debe tener este aspecto:

QtCore.QObject.connect(self.twit_in,
                       QtCore.SIGNAL("newStatuses(list)"),
                       self.update_tweet_list)

Cuando usted emite su señal que debe ser similar al siguiente:

self.emit(SIGNAL("newStatuses(list)"), statuses)

dado que statuses es una lista. Tenga en cuenta que es posible que desee emitir una copia profunda de su lista en función de su situación.

Actualización 2:

Ok, usando list como el tipo no es correcto. A partir de la referencia de ayuda PyQt4:

  

Señales PyQt y señales Qt

     

señales Qt se definen como estáticamente   parte de la clase una C ++. Son   referenciado usando el   QtCore.SIGNAL() función. Esta   método toma un único argumento de cadena   que es el nombre de la señal y su   C ++ firma. Por ejemplo ::

QtCore.SIGNAL("finished(int)")
     

El valor devuelto se pasa normalmente   a la QtCore.QObject.connect()   método.

     

PyQt permite nuevas señales a ser definidos   dinamicamente. El acto de emitir una   PyQt señal que define implícitamente.   señales v4 PyQt también se hace referencia a   usando el QtCore.SIGNAL()   función.

     

El PyQt_PyObject Tipo de señal Argumento

     

Es posible pasar cualquier Python   objeto como un argumento señal por   especificando PyQt_PyObject como el   tipo del argumento en la firma.   Por ejemplo ::

QtCore.SIGNAL("finished(PyQt_PyObject)")
     

Si bien esto normalmente sería utilizado para   pasar objetos como listas y   diccionarios como argumentos de señal, se   puede ser utilizado para cualquier tipo Python. Sus   ventaja cuando se pasa, por ejemplo,   un número entero es que el normal de   las conversiones de un objeto Python a una   número entero C ++ y de nuevo no son   requerido.

     

El recuento de referencia del objeto   ser pasado se mantiene   automáticamente. No hay ninguna necesidad de   el emisor de una señal para mantener una   referencia al objeto después de la llamada   a QtCore.QObject.emit(), incluso si   una conexión se pone en cola.

Al utilizar estas señales / ranuras de estilo antiguo en PyQt, hay en realidad no hay necesidad de declarar tipos en absoluto. Estos deben trabajar:

QtCore.QObject.connect(self.twit_in,
                   QtCore.SIGNAL("newStatuses"),
                   self.update_tweet_list)

...

self.emit(SIGNAL("newStatuses"), statuses)

En este caso, PyQt se acaba de crear un nuevo tipo de señal para que sobre la marcha cuando usted emite la señal. Si quería usuario las señales de nuevo estilo, a continuación, se vería más como:

class TwitterThread(QThread):
    newStatuses = pyqtSignal(object)

....

self.newStatuses.emit(statuses)

señales y ranuras (Py) Qt trabajan transversales hilos de la misma manera como en un solo hilo. Así que no hay nada realmente especial de configurar:

definir una ranura (método) en el hilo principal, y conectar la señal del hilo a esta ranura (la conexión deberá ser también hecho en el hilo principal). Luego, en el hilo, cuando se desea, simplemente emitir la señal y debería funcionar. Aquí hay un tutorial sobre el uso de señales y slots con hilo en PyQt.

Te recomiendo probarlo en un pequeño ejemplo de juguete en primer lugar, antes de pasar a su aplicación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top