Wysyłanie niestandardowych sygnałów PyQt?

Ćwiczę wątki PyQt i (Q), tworząc prostego klienta Twittera. Mam dwa Qthready.

  1. Wątek główny / GUI.

  2. Twitter fetch thread-pobiera dane z Twittera co X minut.

Tak więc, co X minut mój wątek na Twitterze pobiera nowy zestaw aktualizacji statusu (lista Pythona). Chcę przekazać tę listę do głównego wątku / GUI, aby mógł zaktualizować okno o te statusy.

Zakładam, że powinienem używać system signal / slot do przesyłania listy" statusów " Pythona z wątku na Twitterze, do głównego wątku / GUI. Więc moje pytanie jest dwojakie:

  1. Jak wysłać statusy z wątku na Twitterze?

  2. Jak mogę je otrzymać w głównym/GUI wątku?

Z tego co wiem, PyQt może domyślnie wysyłać tylko obiekty PyQt poprzez sygnały / sloty. Myślę, że mam jakoś zarejestrować Niestandardowy sygnał, który mogę następnie wysłać, ale dokumentacja na ten to, co odkryłem, jest bardzo niejasne dla nowicjusza, takiego jak ja. Mam książkę PyQt na zamówienie, ale nie dotrze za tydzień i nie chcę czekać do tego czasu. :-)

Używam PyQt 4.6-1 na Ubuntu

Update:

To fragment kodu, który nie działa. Po pierwsze, staram się" podłączyć " sygnał ("newStatuses", nazwa, którą właśnie wymyśliłem) do jaźni funkcji.update_tweet_list w głównym wątku / GUI:

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

Potem, w wątku na Twitterze, robię to:

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

Po wywołaniu tej linii otrzymuję następujący komunikat:

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

Przeszukałem qregistermetatype (), ale nie znalazłem niczego, co mogłoby zrozumieć Python.

Author: Enfors, 2010-04-06

5 answers

Z tego przykładu:

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

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

Możesz zapisać w Pythonie

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

Edit

Odpowiedź wyciągnięta z komentarza:

self.emit(SIGNAL("newStatuses(PyQt_PyObject)"), statuses)
 7
Author: Xavier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-17 08:12:28

Możesz też to zrobić, co jest o wiele bardziej pythoniczne (i czytelne!).

# 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)
 25
Author: Mark Visser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-07 20:15:58

Spójrz na to pytanie, które zadałem jakiś czas temu. Istnieje przykład kodu, który może pomóc ci dowiedzieć się, co musisz zrobić.

To co powiedziałeś o rejestracji sygnału sprawia, że myślę o tym kodzie (z powyższego pytania):

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

Przekazuję ciągi w moim przykładzie, ale powinieneś być w stanie zastąpić str przez list.

Jeśli okaże się, że nie możesz przekazać mutowalnych obiektów, możesz obsłużyć swoje wyniki tak, jak ja w moim przykładzie (np. Ustaw zmienną results w wątku, powiedz głównemu wątkowi, że są gotowe, i poproś główny wątek "podnieś je").

Update:

Otrzymujesz wiadomość QObject::connect: Cannot queue arguments of type 'statuses', ponieważ musisz zdefiniować Typ argumentu, który przekażesz, gdy wyemitujesz swój sygnał. Typ, który chcesz przekazać, to list, a nie statuses.

Po podłączeniu sygnału powinien wyglądać tak:

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

Kiedy emitujesz swój sygnał powinien wyglądać to:

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

Biorąc pod uwagę, że statuses jest listą. Pamiętaj, że w zależności od sytuacji możesz chcieć wysłać głęboką kopię listy.

Aktualizacja 2:

Ok, użycie {[6] } jako typ nie jest poprawny. Z referencji pomocy PyQt4:

Sygnały PyQt i sygnały Qt

Sygnały Qt są statycznie zdefiniowane jako część klasy C++. Są to / align = "left" / QtCore.SIGNAL() funkcja. To metoda pobiera pojedynczy argument Łańcuchowy że jest nazwą sygnału i jego C++ signature. Na przykład:

QtCore.SIGNAL("finished(int)")

Zwracana wartość jest normalnie przekazywana do QtCore.QObject.connect() metoda.

PyQt pozwala na zdefiniowanie nowych sygnałów dynamicznie. Akt emisji a Sygnał PyQt domyślnie go definiuje. Sygnały PyQt v4 są również przywoływane korzystanie z QtCore.SIGNAL() funkcja.

Typ Argumentu PyQt_PyObject Signal

Możliwe jest podanie dowolnego Pythona obiekt jako argument sygnału przez określenie PyQt_PyObject jako typ argumentu w podpisie. Na przykład:

QtCore.SIGNAL("finished(PyQt_PyObject)")

Podczas gdy zwykle będzie to używane do przekazywanie obiektów takich jak listy i słowniki jako argumenty sygnałowe, to może być używany dla dowolnego typu Pythona. Its przewaga przy przejściu, na przykład, liczba całkowita jest taka, że normalna konwersje z obiektu Pythona na C++ integer I back again nie są wymagane.

Liczba referencji obiektu przekazywana jest utrzymywana automatycznie. Nie ma potrzeby emiter sygnału, aby zachować odniesienie do obiektu po wywołaniu do QtCore.QObject.emit(), nawet jeśli połączenie jest w kolejce.

 7
Author: tgray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:04

Kiedy używasz tych sygnałów / slotów w starym stylu w PyQt, nie ma potrzeby deklarowania typów w ogóle. Powinny działać:

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

...

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

W tym przypadku PyQt po prostu utworzy dla Ciebie nowy typ sygnału w locie, gdy go wyemitujesz. Jeśli chcesz używać sygnałów nowego stylu, to wyglądałoby to bardziej jak:

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

....

self.newStatuses.emit(statuses)
 6
Author: Luke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-03 21:31:49

(Py) sygnały i sloty Qt działają tak samo jak w pojedynczym wątku. Więc nie ma nic specjalnego do skonfigurowania:

Zdefiniuj Gniazdo (metodę) w wątku głównym i podłącz sygnał wątku do tego gniazda (połączenie powinno być również wykonane w wątku głównym). Następnie w wątku, kiedy chcesz, po prostu emituj sygnał i powinien działać. Oto tutorial na temat używania sygnałów i slotów z wątkami w PyQt.

Polecam wypróbować na małej zabawce przykład najpierw, przed przejściem do aplikacji.

 3
Author: Eli Bendersky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-06 14:28:06