web-dev-qa-db-fra.com

Envoi de signaux PYQT personnalisés?

Je pratique des threads pyqt et (q) en faisant un simple client Twitter. J'ai deux qthreads.

  1. Fil principal/interface graphique.

  2. Twitter Fetch thread - récupère les données de Twitter toutes les minutes.

Donc, toutes les minutes X Minutes de Twitter téléchargent un nouvel ensemble de mises à jour d'état (A Python List). Je souhaite remettre cette liste sur le fil principal/interface graphique, de sorte qu'il puisse mettre à jour le fenêtre avec ces statuts.

Je suppose que je devrais utiliser le système Signal/Slot pour transférer les "statuts" Python Liste du thread de Twitter, au fil principal/interface graphique. Donc, ma question est double:

  1. Comment envoyer les statuts du thread Twitter?

  2. Comment les recevoir dans le fil principal/GUI?

Pour autant que je puisse dire, PYQT peut par défaut seulement envoyer des objets PYQT via des signaux/emplacement. Je pense que je suis supposé que je suis censé enregistrer un signal personnalisé que je puisse alors envoyer, mais la documentation à ce sujet que j'ai trouvée n'est pas très peu claire pour un débutant comme moi. J'ai un livre Pyqt sur commande, mais cela n'arrivera pas dans une autre semaine et je ne veux pas attendre jusque-là. :-)

J'utilise Pyqt 4.6-1 sur Ubuntu

Mise à jour :

Ceci est un excessif du code qui ne fonctionne pas. Tout d'abord, j'essaie de "connecter" le signal ("Newstatats", un nom que je viens de maquiller) à la fonction auto.Update_tweet_list dans le fil principal/interface graphique:

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

Ensuite, dans le fil Twitter, je fais cela:

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

Lorsque cette ligne est appelée, je reçois le message suivant:

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

Je l'ai fait une recherche pour qRegisterMetaType () mais je ne trouve pas tout ce qui concerne Python que je pouvais comprendre.

28
Enfors

À partir de cet exemple:

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

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

Vous pouvez écrire à Python

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

Edit

La réponse extraite du commentaire:

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

Vérifiez cela question que j'ai posée un moment. Un exemple de code pourrait vous aider à déterminer ce que vous devez faire.

Ce que vous avez dit sur l'enregistrement de votre signal me fait penser à ce code (de la question susmentionnée):

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

Je passe des cordes dans mon exemple, mais vous devriez être capable de remplacer str avec list.

S'il s'avère que vous ne pouvez pas passer des objets mutables, vous pouvez gérer vos résultats comme je le fais dans mon exemple (c'est-à-dire définir une variable results dans le fil, indiquez le fil principal qu'ils sont prêts, et avoir le fil principal "Choisissez-les").

Mise à jour:

Vous obtenez le message QObject::connect: Cannot queue arguments of type 'statuses' Parce que vous devez définir le type d'argument que vous passerez lorsque vous émettez votre signal. Le type que vous voulez passer est list non statuses.

Lorsque vous connectez votre signal, cela devrait ressembler à ceci:

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

Lorsque vous émettez votre signal, cela devrait ressembler à ceci:

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

étant donné que statuses est une liste. Notez que vous voudrez peut-être émettre une copie profonde de votre liste en fonction de votre situation.

Mise à jour 2:

OK, en utilisant list comme le type n'est pas correct. De la référence d'aide PYQT4:

Signaux PYQT et signaux QT

Les signaux QT sont définis de manière statique dans le cadre d'une classe C++. Ils sont référencés à l'aide de la fonction QtCore.SIGNAL(). Cette méthode prend un argument de chaîne unique qui est le nom du signal et sa signature C++. Par exemple::

QtCore.SIGNAL("finished(int)")

La valeur renvoyée est normalement transmise à la méthode QtCore.QObject.connect().

Pyqt permet de définir de nouveaux signaux de manière dynamique. L'acte d'émettre un signal pyqt le définit implicitement. Les signaux PYQT V4 sont également référencés à l'aide de la fonction QtCore.SIGNAL().

Le type d'argument de signal PyQt_PyObject

Il est possible de passer n'importe quel fichier Python objet comme argument de signal en spécifiant PyQt_PyObject Comme type de l'argument dans la signature. Par exemple ::

QtCore.SIGNAL("finished(PyQt_PyObject)")

Bien que cela soit normalement utilisé pour passer des objets comme des listes et des dictionnaires en tant qu'arguments de signal, il peut être utilisé pour tout Python Type. Son avantage lorsque vous passez, par exemple, un entier est que les conversions normales à partir d'un Python objet à un entier C++ et à nouveau ne sont pas nécessaires.

Le nombre de références de l'objet adopté est maintenu automatiquement. L'émetteur d'un signal n'est pas nécessaire de conserver une référence à l'objet après l'appel à QtCore.QObject.emit(), même si une connexion est en file d'attente.

7
tgray

Lorsque vous utilisez ces signaux/emplacements de style ancien dans Pyqt, il n'est pas nécessaire de déclarer des types du tout. Ceux-ci devraient fonctionner:

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

...

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

Dans ce cas, PyQt va simplement créer un nouveau type de signal pour vous à la volée lorsque vous émettez le signal. Si vous vouliez vous informer des signaux de style neuf, cela ressemblerait davantage à:

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

....

self.newStatuses.emit(statuses)
6
Luke

(PY) Les signaux QT et les machines à sous fonctionnent des fils croisés de la même manière que dans un seul fil. Donc, rien n'est vraiment spécial pour mettre en place:

Définissez une fente (méthode) dans le fil principal et connectez le signal du fil à cette fente (la connexion doit également être effectuée dans le fil principal). Ensuite, dans le fil, lorsque vous voulez, émettez simplement le signal et cela devrait fonctionner. Voici un didacticiel sur l'utilisation des signaux et des emplacements avec filetage dans Pyqt.

Je vous recommande d'essayer d'abord d'essayer d'abord un petit jouet avant de passer à votre application.

3
Eli Bendersky