2016-05-18 3 views
0

Я пытаюсь (и исследую) с небольшим успехом испускать сигнал из рабочего Qthread в главное окно. Кажется, я не понимаю, как мне это сделать в новом синтаксисе.PySide: Извлечение сигнала из QThread в новый синтаксис

Вот простой пример.

from PySide.QtCore import * 
from PySide.QtGui import * 
import sys 
import time 

class Dialog(QDialog): 

    def __init__(self, parent=None): 
     super(Dialog, self).__init__(parent) 

     button = QPushButton("Test me!") 

     layout = QVBoxLayout() 
     layout.addWidget(button) 
     self.setLayout(layout) 

     #self.button.clicked.connect(self.test) ----> 'Dialog' object has no attribute 'button' 
     self.connect(button, SIGNAL('clicked()'), self.test) 
     self.workerThread = WorkerThread() 


    def test(self): 
     self.workerThread.start() 
     QMessageBox.information(self, 'Done!', 'Done.') 


class WorkerThread(QThread): 

    def __init__(self, parent=None): 
     super(WorkerThread, self).__init__(parent) 

    def run(self): 
     time.sleep(5) 
     print "Thread done!" 


app = QApplication(sys.argv) 
dialog = Dialog() 
dialog.show() 
app.exec_() 

Я понимаю, что если у меня не было другого потока я бы создать сигнал внутри диалогового класса и подключить его в __init__, но как я могу создать пользовательский сигнал, который может быть излучаемый из WorkerThread и быть используется тест()?

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

Я на OSX El Capitan, Python 2.7

Любая помощь высоко ценится! Большое спасибо

TL: DR: Я хотел бы передать сигнал WorkerThread через 5 секунд, чтобы тестовая функция отображала QMessageBox только после выполнения WorkThread с использованием нового синтаксиса.

ответ

1

Хорошо, это был долгий день, пытаясь понять это. Мой главный ресурс был таков: http://www.matteomattei.com/pyside-signals-and-slots-with-qthread-example/

В новом синтаксисе для того, чтобы обрабатывать сигналы от различных потоков, вы должны создать класс для сигнала следующим образом:

class WorkerThreadSignal(QObject): 
    workerThreadDone = Signal() 

Это как конец WorkerThread глядя, как:

class WorkerThread(QThread): 

    def __init__(self, parent=None): 
     super(WorkerThread, self).__init__(parent) 
     self.workerThreadSignal = WorkerThreadSignal() 

    def run(self): 
     time.sleep(3) 
     self.workerThreadSignal.workerThreadDone.emit() 

И для соединений на Dialog класса:

self.workerThread = WorkerThread() 
    self.buttonn.clicked.connect(self.test) 

и:

self.workerThreadSignal = WorkerThreadSignal() 
    self.workerThread.workerThreadSignal.workerThreadDone.connect(self.success) 

def success(self): 
    QMessageBox.warning(self, 'Warning!', 'Thread executed to completion!') 

Так метод успеха вызывается после того, как сигнал.

Что мне понадобилось, чтобы выяснить, была ли эта последняя строка кода. Первоначально я думал, что могу подключиться непосредственно к классу WorkerThreadSignal, но, по крайней мере, в этом случае он работал только после того, как я отменил его местоположение. Из диалогового окна init to WorkerThread init назад к WorkerThreadSignal. Я принял этот намек с сайта, упомянутого выше.

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

Я надеюсь, что это поможет кому-то застрять в этом процессе!

PS: Проблема синтаксиса для соединения также была решена. Итак, все написано с новым синтаксисом, и это здорово.

+1

Этот ответ, вероятно, заслуживает собственного вопроса о том, почему то, что вы пытались сделать, не сработало, но я дам его в 500 символах, которые у меня есть! Сигналы уникальны для экземпляра объекта, а не для класса (хотя они и определены как переменная класса).Таким образом, вы сделали два разных сигнала, испустив один, но подключившись к другому. Очевидно, это не сработало! То, что также должно работать, - это просто отбросить класс «WorkerThreadSignal» и переместить сигнал в «WorkerThread», что делает его проще! –

+0

Однако вы можете проверить другой подход к потоковой обработке (рабочая модель), который не перезаписывает 'QThread.run'. См. [This] (http://stackoverflow.com/q/35527439/1994235) и [это] (http://stackoverflow.com/q/37173560/1994235) и [это] (http://stackoverflow.com/q/37195489/1994235) вопрос (а также связанные ссылки там) –

+0

Эй, @three_pineapples, большое спасибо за ссылки и объяснения. Прочитав то, что вы сказали, и другие ресурсы, я начинаю понимать идею использования концепции 'moveToThread(). Я пишу свою первую часть программного обеспечения (после нескольких кучей учебников), поэтому иногда я запутываюсь. Как примечание, перемещение моего сигнала внутри 'workerThread' возвращает, что у объекта нет атрибута« Сигнал », я предполагаю, что это какая-то проблема instancing? –