PySide将信号从QThread传递到另一个QThread中的一个插槽

时间:2016-05-11 21:26:12

标签: python multithreading python-2.7 pyside qthread

  

我通过将mySubQThread run()移到myQThread run()

来解决了我的问题      

那就是说,我仍然想知道为什么我以前尝试过的东西不起作用。

我对线程很新。我遇到了这个问题,我想我可能正在接近错误,无论如何这里都是。我对另一种方法持开放态度,我知道这可能有点令人费解。

我有一个GUI,它使一个新的派生QThread允许在该线程中调用它myQThread,我正在运行一个创建另一个线程的进程调用它mySubQThread我的问题如下所示,我在我的GUI中定义了信号,例如:signalA = QtCore.Signal(int)myQThread中的一个插槽mySubQThread中的插槽似乎永远不会得到信号。

这是一个工作示例。 (略有修改)

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_())

以下是一些示例输出:

请注意,如果您更改了该行:

        self.subThread = mySubQThread(parent=self)

        self.subThread = mySubQThread(parent=None)

它在示例输出中停止抱怨。既没有表明它成为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 个答案:

答案 0 :(得分:3)

问题是因为您已覆盖QThread.run()。默认情况下,run方法包含一个处理信号处理的实现。

如果要正确使用信号/插槽,则应将QObject子类化,将代码放在其中的方法中,然后使用moveToThread()QObject移动到基础实例您实例化的QThread。然后,您可以将方法与QThread.started信号相关联,然后调用thread.start()

来运行代码

然后,您可以通过将该代码放在先前在线程中创建并启动的QObject的方法中,以类似的方式重复创建子线程。你在那里连接的信号和插槽将正确地在线程和它的子线程之间建立。

This是主线​​程与QThread之间正确沟通的一个很好的示例,但您可以轻松地将其扩展到QThreads之间。只需修改MyWorker.firstWork()方法即可启动新的QThread,就像setupThread方法中已经完成的那样。