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

Tom*_*tyn 4 python multithreading pyside qthread python-2.7

我解决了我的问题,通过移动mySubQThread run()myQThread run()

也就是说,我仍然想知道为什么我之前尝试的方法不起作用。

我对线程很陌生。我遇到了这个问题,我想我可能正在处理错误的事情,无论如何。我对不同的方法持开放态度,我知道这可能有点令人费解。

我有一个 GUI 可以创建一个新的派生QThread让我们myQThread在该线程中调用它,我正在运行一个创建另一个线程的进程,调用它mySubQThread我遇到的问题如下,例如,我在 GUI 中定义了信号:signalA = QtCore.Signal(int)和一个插槽in 中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_())
Run Code Online (Sandbox Code Playgroud)

这是一些示例输出:

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

        self.subThread = mySubQThread(parent=self)
Run Code Online (Sandbox Code Playgroud)

        self.subThread = mySubQThread(parent=None)
Run Code Online (Sandbox Code Playgroud)

它不再像在示例输出中那样抱怨。两者都没有表明它达到了 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!
Run Code Online (Sandbox Code Playgroud)

thr*_*les 6

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

如果您想正确使用信号/插槽,您应该子类化QObject,将您的代码放在那里的方法中,并使用moveToThread()将 移动QObjectQThread您实例化的基本实例。然后,您可以通过将您的方法连接到QThread.started信号然后调用来运行您的代码thread.start()

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

是主线程和 a 之间正确通信的一个很好的例子QThread,但您可以轻松地将其扩展到 之间QThreads。只需修改MyWorker.firstWork()方法以启动新的QThread喜欢就已经在setupThread方法中完成了。