Отправка пользовательских сигналов PyQt?

Я практикую PyQt и (Q) потоки путем создания простого клиента Твиттера. У меня есть два Qthreads.

  1. Основной поток / поток GUI.

  2. Поток выборки Твиттера - выбирает данные из Твиттера каждые X минуты.

Так, каждые X минуты мой поток Твиттера загружает новый набор обновлений статуса (список Python). Я хочу передать этот список Основному потоку / потоку GUI, так, чтобы он мог обновить окно с этими состояниями.

Я предполагаю, что должен использовать сигнал / система слота для передачи "состояний" список Python от потока Твиттера к Основному потоку / потоку GUI. Так, мой вопрос является двукратным:

  1. Как я отправляю состояния от потока Твиттера?

  2. Как я получаю их в Основном потоке / потоке GUI?

Насколько я могу сказать, PyQt может по умолчанию только отправить PyQt-объекты через сигналы / слоты. Я думаю, что я, как предполагается, так или иначе регистрирую пользовательский сигнал, который я могу затем отправить, но документация относительно этого, что я нашел, очень неясна новичку как я. Я сделал, чтобы PyQt заказал на порядке, но он не прибудет на другой неделе, и я не хочу ожидать до тех пор.:-)

Я использую PyQt 4.6-1 на Ubuntu

Обновление:

Это - проявление из кода, который не работает. Во-первых, я пытаюсь "соединить" сигнал ("newStatuses", имя, которое я просто составил) к функции сам update_tweet_list в Основном потоке / потоке GUI:

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

Затем в потоке Твиттера я делаю это:

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

Когда эту строку называют, я получаю следующее сообщение:

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

Я сделал поиск qRegisterMetaType (), но я не нашел ничего касающегося Python, который я мог понять.

28
задан Enfors 6 April 2010 в 18:14
поделиться

4 ответа

Из этого примера:

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

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

Вы можете записать в Python

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

Edit

Ответ извлечен из комментария:

self.emit(SIGNAL("newStatuses(PyQt_PyObject)"), statuses)
7
ответ дан 28 November 2019 в 03:17
поделиться

Посмотрите этот вопрос, который я задал некоторое время назад. Вот пример кода, который может помочь вам понять, что вам нужно делать.

То, что вы сказали о регистрации вашего сигнала, заставляет меня думать об этом коде (из вышеупомянутого вопроса):

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

Я передаю строки в своем примере, но вы сможете заменить str на список .

Если выяснится, что вы не можете передавать изменяемые объекты, вы можете обработать свои результаты так, как я это делаю в моем примере (т.е. установить переменную results в потоке, сообщить основному потоку, что они готовы, и пусть основной поток их «подхватит»).

Обновление:

Вы получаете сообщение QObject :: connect: Невозможно поставить в очередь аргументы типа 'статусы' , потому что вам нужно определить тип аргумента, который вы передадите когда вы излучаете свой сигнал. Тип, который вы хотите передать, - это список , а не статусы .

Когда вы подключаете свой сигнал, он должен выглядеть так:

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

Когда вы излучаете свой сигнал, он должен выглядеть так:

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

учитывая, что статусы - это список. Обратите внимание, что вы можете захотеть создать полную копию своего списка в зависимости от вашей ситуации.

Обновление 2:

Хорошо, используется список , поскольку тип неверен. Из справки по PyQt4:

Сигналы PyQt и сигналы Qt

Сигналы Qt статически определены как часть класса C ++. На них ссылаются с помощью функции QtCore.SIGNAL () . Этот метод принимает единственный строковый аргумент , который представляет собой имя сигнала и его сигнатуру C ++. Например ::

 QtCore.SIGNAL ("finished (int)") 
 

Возвращаемое значение обычно передается в QtCore.QObject.connect () метод.

PyQt позволяет динамически определять новые сигналы. Акт испускания сигнала PyQt неявно определяет его. На сигналы PyQt v4 также обращаются с помощью функции QtCore.SIGNAL () .

PyQt_PyObject Тип аргумента сигнала

Можно передать любой объект Python в качестве аргумента сигнала, указав PyQt_PyObject в качестве тип аргумента в подписи. Например ::

 QtCore.SIGNAL ("finished (PyQt_PyObject)") 
 

Хотя обычно это используется для передачи таких объектов, как списки и словари в качестве аргументов сигнала, можно использовать для любого типа Python. Его преимущество при передаче, например, целого числа состоит в том, что обычные преобразования объекта Python в целое число C ++ и обратно не являются {{ 1}} требуется.

Счетчик ссылок переданного объекта поддерживается автоматически. Нет необходимости, чтобы передатчик сигнала сохранял ссылку на объект после вызова QtCore.QObject.emit () , даже если соединение поставлено в очередь.

7
ответ дан 28 November 2019 в 03:17
поделиться

(Py) Сигналы и слоты Qt работают между потоками точно так же, как и в одном потоке. Так что особо нечего настраивать:

Определите слот (метод) в основном потоке и подключите сигнал потока к этому слоту (соединение также должно быть выполнено в основном потоке). Затем в потоке, когда вы хотите, просто испустите сигнал, и он должен работать. Вот руководство по использованию сигналов и слотов с потоковой передачей в PyQt.

Я рекомендую вам сначала попробовать его на небольшом игрушечном примере, прежде чем переходить к вашему приложению.

3
ответ дан 28 November 2019 в 03:17
поделиться

Вы также можете сделать это, что гораздо более питонично (и читается!).

# 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)
26
ответ дан 28 November 2019 в 03:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: