2016-01-29 2 views
2

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

Если я пытаюсь сделать это в одном потоке, все работает нормально - но с этим кодом создается поток, но сигнал никогда не подключается.

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
from PyQt4 import QtCore 

class WorkThread(QtCore.QThread): 
    def __init__(self): 
     QtCore.QThread.__init__(self) 

    def run(self): 
     print("From thread") 
     self.emit(QtCore.SIGNAL("trying")) 
     return 

class Foo(QObject):    
    def handle_trigger(self): 
     print ("trigger signal received") 

    def new_thread(self): 
     self.get_thread = WorkThread() 
     self.connect(self.get_thread, QtCore.SIGNAL("trying"), self.handle_trigger) 
     self.get_thread.start() 


a = Foo() 
a.new_thread() 

ответ

3

Отредактировано на основе комментариев.

Существует одна основная проблема с вашим кодом. На самом деле вы не запускаете приложение Qt, поэтому нет основного цикла событий. Вы должны добавить следующие строки:

app = QApplication(sys.argv) 
app.exec_() 

Кроме того, вы должны использовать new-style Qt signals/slots, если это возможно, или, если придерживаться старого стиля, знайте, что Qt сигнал должен быть в виде функции C, если вы хочу его также work with PySide. Чтобы изменить это для работы с PySide, это будет QtCore.SIGNAL("trying()"), а не QtCore.SIGNAL("trying"). См. Комментарии (особенно мои и комментарии @ ekhumoro) для деталей.

Вот рабочая версия вашего кода (используя сигналы/слоты старого стиля), я попытался изменить наименьшее возможное количество, чтобы вы могли видеть небольшие изменения. Я должен был использовать PySide вместо этого, но он должен работать с PyQt, а также:

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

class WorkThread(QtCore.QThread): 
    def __init__(self): 
     QtCore.QThread.__init__(self) 

    def run(self): 
     print("From thread") 
     self.emit(QtCore.SIGNAL("trying()")) 

class Foo(QObject): 
    def handle_trigger(self): 
     print ("trigger signal received") 
     self.get_thread.quit() 
     self.get_thread.wait() 
     QApplication.quit() 

    def new_thread(self): 
     self.get_thread = WorkThread() 
     self.connect(self.get_thread, QtCore.SIGNAL("trying()"), self.handle_trigger) 
     self.get_thread.start() 

a = Foo() 
a.new_thread() 

app = QApplication(sys.argv) 
app.exec_() 

А вот вариант, используя новый стиль сигнал/слот (см @three_pineapples комментарий). Это рекомендуемый способ реализации сигналов/слотов в PyQt/PySide.

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

class WorkThread(QtCore.QThread): 
    ranThread = QtCore.Signal() 
    # for PyQt, use QtCore.pyqtSignal() instead 

    def __init__(self): 
     QtCore.QThread.__init__(self) 

    def run(self): 
     print("From thread") 
     self.ranThread.emit() 

class Foo(QObject): 
    def handle_trigger(self): 
     print ("trigger signal received") 
     self.get_thread.quit() 
     self.get_thread.wait() 
     QApplication.quit() 

    def new_thread(self): 
     self.get_thread = WorkThread() 
     self.get_thread.ranThread.connect(self.handle_trigger) 
     self.get_thread.start() 

a = Foo() 
a.new_thread() 

app = QApplication(sys.argv) 
app.exec_() 
+2

Чтобы избежать подобных ошибок в будущем, лучше просто переключиться на новый стиль сигналов и слотов. Дополнительную информацию см. В документации [PyQt документации] (http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html). –

+0

Согласен с тем, что сказал @three_pineapples. Но неправильно говорить, что определения старого стиля должны быть в форме функции. Фактически, ** любая ** строка может использоваться для пользовательского сигнала - даже пустая строка! Единственное, что имеет значение, это то, что строки соответствуют (хотя и не точно) - пробелы игнорируются). Реальная ошибка в примере OPs состоит в том, что он не запускает цикл событий, который требуется для обработки асинхронных сигналов с поперечной резьбой, но не для синхронных, прямых сигналов. – ekhumoro

+0

На моем компьютере с PySide, оставляя скобки, возникает ошибка сегментации. – Steve

1

Я смутил это сам, и я думаю, что это сработает для вас.

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
from PyQt4 import QtCore 

class WorkThread(QtCore.QThread): 
def __init__(self): 
    QtCore.QThread.__init__(self) 

tryThis = QtCore.Signal(str) #added this variable 

def run(self): 
    print("From thread") 
    x = "trying" 
    self.tryThis.emit(QtCore.SIGNAL(x)) #pass your new variable like this 
    return 

class Foo(QObject): 

    def handle_trigger(self): 
     print ("trigger signal received") 

    def new_thread(self): 
     self.get_thread = WorkThread()   
     self.get_thread.start() 
     self.get_thread.tryThis.connect(self.handle_trigger,QtCore.Qt.QueuedConnection) #passed it here 

a = Foo() 
a.new_thread() 
Смежные вопросы