[英]PyQt wake main thread from non-QThread
我有一个 PyQt 应用程序,它通过从不受我控制且不是QThread
线程调用的回调接收来自外部源的信息。 将此类信息传递给主线程而不进行轮询的正确方法是什么? 特别是,我想发出一个 Qt 信号,这样我就可以在新数据到达时唤醒主线程(或另一个QThread
)。
信号的默认连接类型是Qt.AutoConnection ,文档是这样描述的:
如果信号是从与接收对象不同的线程发出的,则信号将排队,表现为 Qt::QueuedConnection。 否则,将直接调用插槽,表现为 Qt::DirectConnection。 连接类型是在发出信号时确定的。
因此,在发出信号之前,Qt 会在决定是否将其排队之前简单地比较发送方和接收方的当前线程关联。 底层线程最初是如何启动的并不重要。
这是一个使用 python 工作线程的简单演示:
import sys, time, threading
from PyQt4 import QtCore, QtGui
class Worker(object):
def __init__(self, callback):
self._callback = callback
self._thread = None
def active(self):
return self._thread is not None and self._thread.is_alive()
def start(self):
self._thread = threading.Thread(target=self.work, name='Worker')
self._thread.start()
def work(self):
print('work: [%s]' % threading.current_thread().name)
for x in range(5):
time.sleep(1)
self._callback(str(x))
class Window(QtGui.QPushButton):
dataReceived = QtCore.pyqtSignal(str)
def __init__(self):
super(Window, self).__init__('Start')
self.clicked.connect(self.start)
self.dataReceived.connect(self.receive)
self.worker = Worker(self.callback)
def receive(self, data):
print('received: %s [%s]' % (data, threading.current_thread().name))
def callback(self, data):
print('callback: %s [%s]' % (data, threading.current_thread().name))
self.dataReceived.emit(data)
def start(self):
if self.worker.active():
print('still active...')
else:
print('start: [%s]' % threading.current_thread().name)
self.worker.start()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
print('show: [%s]' % threading.current_thread().name)
sys.exit(app.exec_())
典型输出:
$ python test.py
show: [MainThread]
start: [MainThread]
work: [Worker]
callback: 0 [Worker]
received: 0 [MainThread]
still active...
callback: 1 [Worker]
received: 1 [MainThread]
still active...
callback: 2 [Worker]
received: 2 [MainThread]
still active...
callback: 3 [Worker]
received: 3 [MainThread]
callback: 4 [Worker]
received: 4 [MainThread]
如果您只是轮询外部设备或库,我会像处理它一样处理它。 创建一个单独的工作线程来处理回调,并向主 GUI 线程发出信号。
class Worker(QObject):
data_ready = pyqtSignal(object, object)
def callback(self, *args, **kwargs):
self.data_ready.emit(args, kwargs)
class Window(...)
def __init__(self):
...
self.worker = Worker(self)
# Connect worker callback function to your external library
library.register_callback(self.worker.callback) #??
...
# Mover worker to thread and connect signal
self.thread = QThread(self)
self.worker.data_ready.connect(self.handle_data)
self.worker.moveToThread(self.thread)
self.thread.start()
@pyqtSlot(object, object)
def handle_data(self, args, kwargs):
# do something with data
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.