2016-05-11 2 views
0

Je résolu mon problème en déplaçant le mySubQThreadrun() dans le myQThreadrun()PySide signaux passant de QThread à une fente dans un autre QThread

Cela dit, je voudrais encore savoir pourquoi ce que je tentais avant didn » t travail.

Je suis assez nouveau pour le threading. Je me heurte à cette question et je pense que je peux aborder les choses mal, de toute façon ici va. Je suis ouvert à une approche différente, je sais que cela peut être un peu compliqué à suivre.

J'ai une interface graphique qui fait une nouvelle dérivée QThread permet de l'appeler myQThread dans ce fil, je suis en cours d'exécution à travers un processus qui crée un autre thread appeler mySubQThread la question que j'ai est la suivante, je signaux définis dans mon GUI par exemple: signalA = QtCore.Signal(int) et un emplacement dans myQThread L'emplacement dans le mySubQThread ne semble jamais obtenir le signal.

Voici un exemple de travail. (Un peu modifié)

from PySide import QtCore, QtGui 
import time 



class myQThread(QtCore.QThread): 
    myThreadSignal = QtCore.Signal(int) 
    def __init__(self, parent): 
     super(myQThread, self).__init__(parent=parent) 

    def run(self): 
     self.subThread = mySubQThread(parent=self) 
     self.myThreadSignal.connect(self.subThread.sub_thread_slot) 
     self.myThreadSignal.connect(self.test_slot) 
     print "starting subthread..." 
     self.subThread.start() 

     while self.subThread.isRunning(): 
      print "myQThread is alive!" 
      time.sleep(1) 
     print "myQThread exiting run..." 
    @QtCore.Slot(int) 
    def my_thread_slot(self, a): 
     print "1b) Made it here!" 
     self.myThreadSignal.emit(a) 

    @QtCore.Slot(int) 
    def test_slot(self, a): 
     print "2a) Made it here!" 

class mySubQThread(QtCore.QThread): 
    mySubSignalA = QtCore.Signal(int) 
    def __init__(self, parent): 
     super(mySubQThread, self).__init__(parent=parent) 
     self._abort = False 
    def run(self): 
     #Do some processing 
     #Wait for signal 
     self._abort = False 
     while not self._abort: 
      print "mySubQThread is alive!" 
      time.sleep(1) 
     print "mySubQThread exiting run..." 

    @QtCore.Slot(int) 
    def sub_thread_slot(self, a): 
     print "2b)Never make it here!" 
     self._abort = True 


class myWidget(QtGui.QWidget): 
    myWidgetSignal = QtCore.Signal(int) 
    def __init__(self, parent=None): 
     super(myWidget, self).__init__(parent=parent) 
     #simple Widget to test this out.... 
     myLayout = QtGui.QVBoxLayout() 
     self.runButton = QtGui.QPushButton("run") 
     self.runButton.clicked.connect(self.run_button_pressed) 

     self.otherButton = QtGui.QPushButton("other") 
     self.otherButton.clicked.connect(self.other_button_pressed) 

     myLayout.addWidget(self.runButton) 
     myLayout.addWidget(self.otherButton) 

     self.setLayout(myLayout) 
    @QtCore.Slot() 
    def run_button_pressed(self): 
     self.processThread = myQThread(self) 
     self.myWidgetSignal.connect(self.processThread.my_thread_slot) 
     self.myWidgetSignal.connect(self.test_slot) 
     self.processThread.start() 
    @QtCore.Slot() 
    def other_button_pressed(self): 
     self.myWidgetSignal.emit(1) 

    @QtCore.Slot(int) 
    def test_slot(self, a): 
     print "1a) Made it here!" 

if __name__ == "__main__": 
    import sys 
    myApp = QtGui.QApplication(sys.argv) 
    myWin = myWidget() 
    myWin.show() 
    sys.exit(myApp.exec_()) 

Voici une exemple de sortie:

Notez que si vous modifiez la ligne:

 self.subThread = mySubQThread(parent=self) 

à

 self.subThread = mySubQThread(parent=None) 

il cesse de se plaindre comme il le fait dans la sortie de l'échantillon. ne montre qu'il fait à 2B

QObject: Cannot create children for a parent that is in a different thread. 
(Parent is myQThread(0x3c3faf0), parent's thread is QThread(0x2792548), current thread is myQThread(0x3c3faf0) 
starting subthread... 
myQThread is alive!mySubQThread is alive! 

mySubQThread is alive! 
myQThread is alive! 
1b) Made it here! 
2a) Made it here! 
1a) Made it here! 
+1

Vérifiez les documents: http://doc.qt.io/qt-4.8/qthread.html#détails juste en dessous de l'exemple 'WorkerThread'. Il fournit plus d'explications pour expliquer pourquoi les slots sur QThreads ne fonctionnent pas comme on pourrait s'y attendre. – sebastian

+0

@sebastian Merci! J'ai lu cela quelques fois avant, maintenant c'est plus logique. –

+0

Je suis maintenant convaincu d'utiliser le modèle de travailleur. –

Répondre

2

Le problème est que vous avez remplacé QThread.run(). La méthode run contient par défaut une implémentation qui gère le traitement du signal.

Si vous souhaitez utiliser les signaux/slots correctement vous devez sous-classe QObject, mettre votre code dans une méthode là-dedans, et utiliser moveToThread() pour déplacer le QObject à une instance de base de QThread que vous instancier. Vous pouvez ensuite exécuter votre code en connectant votre méthode au signal QThread.started puis appeler thread.start()

Vous pouvez répéter la création du fil de l'enfant d'une manière similaire, en mettant ce code dans la méthode de l'QObject précédemment créé et lancé dans le fil. Les signaux et les slots que vous connectez là seront créés entre le thread et son thread fils correctement.

This est un bon exemple de communication appropriée entre le thread principal et un QThread, mais vous pouvez facilement l'étendre entre QThreads. Il suffit de modifier la méthode MyWorker.firstWork() pour lancer un nouveau QThread comme cela est déjà fait dans la méthode setupThread.

+1

Je suis maintenant entièrement convaincu d'utiliser le modèle de travailleur. –