Domanda

Sto praticando PyQt e (Q)thread, con un semplice client Twitter.Ho due Qthreads.

  1. Principale/GUI thread.

  2. Twitter fetch filo - recupera i dati da Twitter ogni X minuti.

Così, ogni X minuti il mio Twitter thread download una nuova serie di aggiornamenti di stato (una lista Python).Voglio a portata di mano questo elenco sopra al menu Principale/GUI thread, in modo che è possibile aggiornare la finestra con questi stati.

Sto assumendo che dovrebbe usare il signal / slot per trasferire le "status" lista Python da Twitter thread, la Principale/GUI thread.Così, la mia domanda è duplice:

  1. Come faccio a inviare gli status di Twitter thread?

  2. Come faccio a ricevere l'/GUI thread?

Per quanto posso dire, PyQt possibile per impostazione predefinita solo inviare PyQt-oggetti tramite segnali / slot.Penso che dovrei in qualche modo registrare un segnale che poi posso inviare, ma la documentazione su questa che ho trovato è molto chiaro per un newbie come me.Ho un PyQt libro su ordinazione, ma non si arriva in un'altra settimana, e non ho voglia di aspettare fino ad allora.:-)

Sto usando PyQt 4.6-1 su Ubuntu

Aggiornamento:

Questo è un esercitare il codice che non funziona.Prima, cerco di "collegare" il segnale ("newStatuses", un nome che ho appena fatto) per la funzione di auto.update_tweet_list Principale/GUI thread:

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

Quindi, in Twitter thread, faccio questo:

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

Quando questa linea è chiamata, ricevo il seguente messaggio:

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

Ho fatto una ricerca per qRegisterMetaType() ma non ho trovato nulla che riguardi Python che ho potuto capire.

È stato utile?

Soluzione

Da questo esempio:

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

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

Si può scrivere in Python

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

Modifica

La risposta estratto dal commento:

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

Altri suggerimenti

È anche possibile fare questo, che è molto più divinatori (e leggibile!).

# 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)

Check out questo domanda che ho fatto un po ' indietro.C'è un esempio di codice che potrebbe aiutare a capire che cosa dovete fare.

Quello che hai detto sulla registrazione del segnale mi fa pensare a questo codice (dalla predetta domanda):

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

Sto passando le stringhe nel mio esempio, ma si dovrebbe essere in grado di sostituire str con list.

Se si scopre che non è possibile passare oggetti mutabili, è in grado di gestire i vostri risultati il mio modo di fare nel mio esempio (cioèimpostare un results variabile nel thread, dire il thread principale che sono pronti, e hanno il thread principale "raccoglierli").

Aggiornamento:

Si ottiene il messaggio QObject::connect: Cannot queue arguments of type 'statuses' perché è necessario definire il tipo di argomento che si passa quando si emette il segnale.Il tipo che si desidera passare è list non statuses.

Quando si collega il segnale dovrebbe assomigliare a questo:

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

Quando si emettono il segnale dovrebbe assomigliare a questo:

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

dato che statuses è un elenco.Si noti che è possibile che si desideri creare una copia completa della tua lista a seconda della situazione.

Aggiorna 2:

Ok, con list come il tipo non è corretto.Dal PyQt4 guida di riferimento:

PyQt Segnali e Segnali Qt

Qt segnali sono definite staticamente come parte di una classe C++.Sono riferimento utilizzando la QtCore.SIGNAL() funzione.Questo il metodo accetta un solo argomento stringa che è il nome del segnale e la sua C++ firma.Per esempio::

QtCore.SIGNAL("finished(int)")

Il valore restituito è normalmente passati per il QtCore.QObject.connect() metodo.

PyQt permette nuovi segnali per essere definiti in modo dinamico.L'atto di emissione PyQt segnale implicitamente definisce.PyQt v4 segnali sono anche fatto riferimento utilizzando il QtCore.SIGNAL() funzione.

Il PyQt_PyObject Segnale Tipo Di Argomento

È possibile passare qualsiasi Python oggetto come argomento del segnale da specifica PyQt_PyObject come tipo dell'argomento in firma.Per esempio::

QtCore.SIGNAL("finished(PyQt_PyObject)")

Mentre questo sarebbe normalmente essere utilizzato per il passaggio di oggetti, come le liste e dizionari come segnale di argomenti, può essere utilizzato per qualsiasi tipo Python.La sua vantaggio quando si passa, per esempio, un numero intero è che la normale le conversioni da un oggetto Python per un C++ intero e di nuovo non sono richiesto.

Il numero di riferimento dell'oggetto essendo passato è mantenuto automaticamente.Non c'è bisogno di l'emettitore di segnale per mantenere un riferimento all'oggetto, dopo la chiamata per QtCore.QObject.emit(), anche se una connessione è in coda.

Quando si utilizza questi vecchio stile segnali/slot in PyQt, non c'è bisogno di dichiarare i tipi di tutti.Questi dovrebbe funzionare:

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

...

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

In questo caso, PyQt sarà solo creare un nuovo tipo di segnale per voi al volo quando si emette il segnale.Se si voleva utente il nuovo stile di segnali, quindi sarebbe un aspetto più simile a:

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

....

self.newStatuses.emit(statuses)

(Py)Qt segnali e slot di lavoro cross-thread proprio come in un unico thread.Quindi non c'è niente di veramente speciale per impostare:

Definire uno slot (metodo) nel thread principale e collegare il filo del segnale a questa slot (il collegamento deve essere fatto anche nel thread principale).Poi, nel thread, quando si vuole, basta emettere il segnale e dovrebbe funzionare. Ecco un tutorial sull'utilizzo di segnali e slot, con filettatura in PyQt.

Vi consiglio di provarlo su un piccolo giocattolo esempio di prima, prima di passare all'applicazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top