Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在使用PyQt5的正确线程中未接收到信号_Python_Multithreading_Qt_Pyqt_Pyqt5 - Fatal编程技术网

Python 在使用PyQt5的正确线程中未接收到信号

Python 在使用PyQt5的正确线程中未接收到信号,python,multithreading,qt,pyqt,pyqt5,Python,Multithreading,Qt,Pyqt,Pyqt5,因此,在充分理解了如何正确使用Qt中的线程之后,我编写了一个小玩具示例,其中一个QObject被移动到一个正在运行的线程,当单击窗口时,该对象上会调用一个信号 我遇到的问题是插槽从来没有在正确的线程中调用过——它总是在主线程中调用 这是通过以下代码实现的: from PyQt5 import QtWidgets, QtCore class WidgetWithInput(QtWidgets.QWidget): widgetClicked = QtCore.pyqtSignal()

因此,在充分理解了如何正确使用Qt中的线程之后,我编写了一个小玩具示例,其中一个
QObject
被移动到一个正在运行的线程,当单击窗口时,该对象上会调用一个信号

我遇到的问题是插槽从来没有在正确的线程中调用过——它总是在主线程中调用

这是通过以下代码实现的:

from PyQt5 import QtWidgets, QtCore

class WidgetWithInput(QtWidgets.QWidget):

    widgetClicked = QtCore.pyqtSignal()

    def mousePressEvent(self, event):
        self.widgetClicked.emit()

class MyObject(QtCore.QObject):

    aSignal = QtCore.pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(MyObject, self).__init__(*args, **kwargs)

        self.aSignal.connect(self.onASignal)

    def onASignal(self):
        print('MyObject signal thread: %s'
               % str(int(QtCore.QThread.currentThreadId())))


class SimpleDisplay(QtWidgets.QMainWindow):
    ''' Class presenting the display subsytem
    '''

    def __init__(self, my_object, *args, **kwargs):

        super(SimpleDisplay, self).__init__(*args, **kwargs)

        self._my_object = my_object

        self._widget = WidgetWithInput()

        self.setCentralWidget(self._widget)
        self._widget.widgetClicked.connect(self._do_something)

    def _do_something(self):
        self._my_object.aSignal.emit()

def main(run_until_time=None):

    import sys
    app = QtWidgets.QApplication(sys.argv)
    print ('main thread: %s' % str(int(QtCore.QThread.currentThreadId())))

    concurrent_object = MyObject()
    display = SimpleDisplay(concurrent_object)

    myobject_thread = QtCore.QThread()
    myobject_thread.start()

    concurrent_object.moveToThread(myobject_thread)

    display.show()

    exit_status = app.exec_()

    myobject_thread.quit()
    myobject_thread.wait()

    sys.exit(exit_status)

if __name__ == '__main__':
    main()
其输出类似于:

main thread: 139939383113472
MyObject signal thread: 139939383113472
我希望这两个打印的线程ID是不同的


我是不是遗漏了什么?显式设置要排队的信号不会改变任何事情。

多亏了@three_pinapples,他在评论中的建议解决了这个问题:插槽需要用
QtCore.pyqtlot
装饰:

class MyObject(QtCore.QObject):

    aSignal = QtCore.pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(MyObject, self).__init__(*args, **kwargs)

        self.aSignal.connect(self.onASignal)

    @QtCore.pyqtSlot()
    def onASignal(self):
        print('MyObject signal thread:\t %s'
               % str(int(QtCore.QThread.currentThreadId())))

感谢@three_pinapples,他在评论中的建议解决了这个问题:插槽需要用
QtCore.pyqtlot
装饰:

class MyObject(QtCore.QObject):

    aSignal = QtCore.pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(MyObject, self).__init__(*args, **kwargs)

        self.aSignal.connect(self.onASignal)

    @QtCore.pyqtSlot()
    def onASignal(self):
        print('MyObject signal thread:\t %s'
               % str(int(QtCore.QThread.currentThreadId())))

在将
MyObject
实例移动到新线程之前,您似乎正在触发
MyObject.aSignal
信号。因此,您看到的输出。@G.M.我理解信号是在对象的线程中接收的。我很高兴在这一点上错了,但我不清楚如何将信号连接到正确的线程中。我尝试了几件事,比如在
ThreadChange
事件上发出一个新的信号(这在概念上是线程更改之前的最后一个事件),一个连接信号的处理程序,但没有起作用(与之前的结果相同)。我可以通过在
main
函数中显式地执行它来让它工作,但这需要我的
main
具备应该限制在IMO类的知识。此外,我可以通过将线程传递到
MyObject
来解决问题,然后在
\uuuu init\uuuu
中使用
self.moveToThread
。这对我来说似乎有点麻烦,因为它需要MyObject知道它所在的线程。除非用
pyqtSlot
函数装饰插槽,否则连接信号和将对象移动到线程的顺序很重要。我将其标记为(请参阅)副本的问题是针对PyQt4,但我相信它也会转换为PyQt5。在将
MyObject
实例移动到新线程之前,您似乎正在触发
MyObject.aSignal
信号。因此,您看到的输出。@G.M.我理解信号是在对象的线程中接收的。我很高兴在这一点上错了,但我不清楚如何将信号连接到正确的线程中。我尝试了几件事,比如在
ThreadChange
事件上发出一个新的信号(这在概念上是线程更改之前的最后一个事件),一个连接信号的处理程序,但没有起作用(与之前的结果相同)。我可以通过在
main
函数中显式地执行它来让它工作,但这需要我的
main
具备应该限制在IMO类的知识。此外,我可以通过将线程传递到
MyObject
来解决问题,然后在
\uuuu init\uuuu
中使用
self.moveToThread
。这对我来说似乎有点麻烦,因为它需要MyObject知道它所在的线程。除非用
pyqtSlot
函数装饰插槽,否则连接信号和将对象移动到线程的顺序很重要。我将其标记为(请参阅)的副本的问题是针对PyQt4的,但我相信它也会转换为PyQt5。