PySide将信号从QThread传递到另一个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!

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

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

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

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

最新更新