【发布时间】:2019-12-04 14:52:34
【问题描述】:
在 Qt/PyQt 中,我曾经使用 Worker 类和 QThread 进行线程化。
self.worker = Worker()
self.thread = QThread()
worker.moveToThread(thread)
setup_signal_slot_with_main_object()
// start
thread.start()
我必须将 setup_signal_slot_with_main_object() 放在 moveToThread() 之后。但我有一个复杂的工人。在 Worker.__ init__() 中,它创建了许多 QObject 并连接内部信号和插槽。我不想创建一个在 worker->moveToThread(&thread) 之后建立所有连接并调用 worker.setup_signal_slot() 的方法,因为 Worker 包含许多子 QObject,每个QObject 可以在其构造函数中制作信号/槽。
在 Qt/C++ 中,我可以在 worker 的构造函数中建立信号/槽连接。但是在 PyQt 中,slot 不会在新线程中运行。
这是一个包含 QTimer 的 Worker 的示例
import sys
import signal
import threading
from PyQt5.QtCore import QObject, pyqtSignal, QTimer, QCoreApplication, QThread
import datetime
class Worker(QObject):
timeChanged = pyqtSignal(object)
def __init__(self, parent=None):
QObject.__init__(self, parent)
self.timer = QTimer(self)
self.timer.setInterval(1000)
# I want to make connection at here
self.timer.timeout.connect(self.main_process)
def start(self):
# self.timer.timeout.connect(self.main_process)
self.timer.start()
print('Worker thread {}: Start timer'.format(threading.get_ident()))
# this method still run in main thread
def main_process(self):
timestamp = datetime.datetime.now()
print('Worker thread {}: {}'.format(threading.get_ident(), timestamp.strftime('%d-%m-%Y %H-%M-%S')))
self.timeChanged.emit(timestamp)
class WorkerThread(QObject):
def __init__(self, parent=None):
QObject.__init__(self, parent)
self.emitter = Worker()
self.thread = QThread(self)
self.emitter.moveToThread(self.thread)
self.thread.started.connect(self.emitter.start)
self.thread.finished.connect(self.emitter.deleteLater)
self.emitter.timeChanged.connect(self.show_time)
def start(self):
self.thread.start()
def stop(self):
if self.thread.isRunning():
self.thread.quit()
self.thread.wait()
print('Exit thread')
def show_time(self, timestamp):
print('Main thread {}: {}'.format(threading.get_ident(), timestamp.strftime('%d-%m-%Y %H-%M-%S')))
def signal_handler(sig, frame):
print('Quit')
app.quit()
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
app = QCoreApplication(sys.argv)
timer = QTimer()
timer.timeout.connect(lambda: None)
timer.start(500)
print('Main thread {}'.format(threading.get_ident()))
emitter = WorkerThread()
emitter.start()
sys.exit(app.exec_())
在Worker中,定时器超时会在主线程中调用main_process。我可以将 self.timer.timeout.connect(self.main_process) 移动到方法 worker.start() 中。但正如我上面所说,我仍然想在其构造函数中放置内部信号/插槽。 谁能建议我一个解决方案?谢谢!
【问题讨论】:
标签: python pyqt pyqt5 qthread qobject