Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.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/6/multithreading/4.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 使用QRunnable执行线程-发送双向回调的正确方式_Python_Multithreading_Pyqt_Pyqt5_Signals Slots - Fatal编程技术网

Python 使用QRunnable执行线程-发送双向回调的正确方式

Python 使用QRunnable执行线程-发送双向回调的正确方式,python,multithreading,pyqt,pyqt5,signals-slots,Python,Multithreading,Pyqt,Pyqt5,Signals Slots,,我已经看到可以使用信号和插槽将工作线程回调到主GUI线程,但我不确定如何使用信号和插槽建立双向通信。以下是我的工作内容: class RespondedToWorkerSignals(QObject): callback_from_worker = pyqtSignal() class RespondedToWorker(QRunnable): def __init__(self, func, *args, **kwargs): super(Responded

,我已经看到可以使用信号和插槽将工作线程回调到主GUI线程,但我不确定如何使用信号和插槽建立双向通信。以下是我的工作内容:

class RespondedToWorkerSignals(QObject):
    callback_from_worker = pyqtSignal()

class RespondedToWorker(QRunnable):
    def __init__(self, func, *args, **kwargs):
        super(RespondedToWorker, self).__init__()
        self._func = func
        self.args = args
        self.kwargs = kwargs
        self.signals = RespondedToWorkerSignals()
        self.kwargs['signal'] = self.signals.callback_from_worker
        print("Created a responded-to worker")

    @pyqtSlot()
    def run(self):
        self._func(*self.args, **self.kwargs)

    @pyqtSlot()
    def acknowledge_callback_in_worker(self):
        print("Acknowledged Callback in Worker")

class MainWindow(QMainWindow):

    # Signal meant to connect to a slot present within a worker
    mainthread_callback_to_worker = pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        # Quick UI setup
        w, lay = QWidget(), QVBoxLayout()
        w.setLayout(lay)
        self.setCentralWidget(w)
        self.timer_label = QLabel("Timer Label")
        lay.addWidget(self.timer_label)
        self.btn_thread_example = QPushButton("Push Me")
        self.btn_thread_example.pressed.connect(self.thread_example)
        lay.addWidget(self.btn_thread_example)
        self.threadpool = QThreadPool()
        self.show()

        # Set up QTimer to continue in the background to help demonstrate threading advantage
        self.counter = 0
        self.timer = QTimer()
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.recurring_timer)
        self.timer.start()

    @pyqtSlot()
    def do_something(self, signal):
        # signal argument will be the callback_from_worker and it will emit to acknowledge_callback_in_mainthread
        print("do_something is sleeping briefly. Try to see if you get a locked widget...")
        time.sleep(7)
        signal.emit()

    @pyqtSlot()
    def acknowledge_callback_in_mainthread_and_respond(self):
        # this function should respond to callback_from_worker and emit a response
        print("Acknowledged Callback in Main")
        self.mainthread_callback_to_worker.emit()

    def thread_example(self):
        print("Beginning thread example")
        worker = RespondedToWorker(self.do_something)
        worker.signals.callback_from_worker.connect(self.acknowledge_callback_in_mainthread_and_respond)
    # self.mainthread_callback_to_worker.connect(worker.acknowledge_callback_in_worker) # <-- causes crash

    def recurring_timer(self):
        self.counter += 1
        self.timer_label.setText(f"Counter: {self.counter}")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = MainWindow()
    app.setStyle("Fusion")
    win.show()
    sys.exit(app.exec())
类响应的工作信号(QObject):
从\u worker=pyqtSignal()回调\u
类响应的ToWorker(QRunnable):
定义初始化(self,func,*args,**kwargs):
超级(响应的工作人员,自我)。\uuuu init\uuuu()
self._func=func
self.args=args
self.kwargs=kwargs
self.signals=响应的工作信号()
self.kwargs['signal']=self.signals.callback\u来自\u worker
打印(“创建了一个响应的工作人员”)
@pyqtSlot()
def运行(自):
self._func(*self.args,**self.kwargs)
@pyqtSlot()
def确认\u回拨\u输入\u工作者(自我):
打印(“工作进程中已确认的回调”)
类主窗口(QMainWindow):
#用于连接到工作机中存在的插槽的信号
mainthread\u callback\u to\u worker=pyqtSignal()
定义初始化(self,*args,**kwargs):
超级(主窗口,自我)。\uuuuu初始化(*args,**kwargs)
#快速用户界面设置
w、 lay=QWidget(),QVBoxLayout()
w、 设置布局(布局)
self.setCentralWidget(w)
self.timer_label=QLabel(“计时器标签”)
lay.addWidget(self.timer\u标签)
self.btn_thread_示例=QPushButton(“推我”)
self.btn\u线程\u示例。按下。连接(self.thread\u示例)
lay.addWidget(self.btn\u线程\u示例)
self.threadpool=QThreadPool()
self.show()
#设置QTimer以在后台继续,以帮助演示线程优势
self.counter=0
self.timer=QTimer()
自动定时器设置间隔(1000)
self.timer.timeout.connect(self.recurtive\u timer)
self.timer.start()
@pyqtSlot()
def do_某事(自身、信号):
#signal参数将是来自\u worker的回调\u,它将在\u主线程中发出以确认\u回调\u
打印(“do_某事正在短暂休眠。尝试查看是否有锁定的小部件…”)
时间。睡眠(7)
signal.emit()
@pyqtSlot()
主线程中的def确认回调和响应(自我):
#此函数应响应来自\u worker的回调\u并发出响应
打印(“主屏幕中已确认的回调”)
self.mainthread\u回调\u到\u worker.emit()
def螺纹_示例(自):
打印(“开始线程示例”)
worker=响应的worker(self.do\u something)
worker.signals.callback\u来自\u worker.connect(self.acknowledge\u callback\u在\u主线程中\u和\u响应)

#self.mainthread_callback_to_worker.connect(worker.acknowledge_callback_in_worker)#要了解错误原因,您必须在终端中运行代码,并会收到以下错误消息:

QObject::connect: Cannot connect MainWindow::mainthread_callback_to_worker() to (nullptr)::acknowledge_callback_in_worker()
Traceback (most recent call last):
  File "main.py", line 72, in thread_example
    self.mainthread_callback_to_worker.connect(worker.acknowledge_callback_in_worker) # <-- causes crash
TypeError: connect() failed between MainWindow.mainthread_callback_to_worker[] and acknowledge_callback_in_worker()
Aborted (core dumped)

谢谢你的解释。在进一步研究之后,我还想让任何读者知道,根据我所犯的另一个错误,就是遗漏了一个细节,即QRunnable+QThreadPool不支持“通过信号进行数据更新”,也不支持“使用信号进行控制”。您似乎没有阅读网站的文档,因此我建议您检查并通过。此处的标题不会通过添加已解决的问题来修改,或者编辑问题以添加可能的解决方案,您必须在此处将答案标记为正确,并在“答案”部分中发布答案。注意:您应该始终阅读所使用技术的文档(例如Qt和StackOverflow文档)