QRunnable 中的计时器
Posted
技术标签:
【中文标题】QRunnable 中的计时器【英文标题】:Timer in a QRunnable 【发布时间】:2020-05-26 15:45:56 【问题描述】:我在this answer 的帮助下创建了以下玩具类:
class Worker(QtCore.QThread):
def work(self):
print("message")
def __init__(self):
super(Worker, self).__init__()
self.timer = QtCore.QTimer()
self.timer.moveToThread(self)
self.timer.timeout.connect(self.work)
def run(self):
self.timer.start(1000)
loop = QtCore.QEventLoop()
loop.exec_()
当我使用QThreadPool
时,如何从新线程启动计时器?
我需要定期重复更新 GUI,但如果我在主线程中添加 QTimer
,整个应用程序会感觉非常缓慢。我的理解是,通过 QThreadPool
将其包含在单独的线程中,这可能是一个更有效的解决方案,因为新线程可以在完成后自动自行删除。
但是,每当我在上面的类中将 QtCore.QThread
更改为 QtCore.QRunnable
并尝试使用下面的代码启动线程时,我都会收到错误:
self.threadpool = QtCore.QThreadPool()
worker = Worker()
self.threadpool.start(worker)
【问题讨论】:
【参考方案1】:如果您想使用 QThreadPool 每 T 秒运行一次任务,那么 QTimer 不必存在于另一个线程中,而是 QTimer 启动 QRunnable:
import json
import random
import threading
import time
from PyQt5 import QtCore, QtGui, QtWidgets
import sip
class Signaller(QtCore.QObject):
dataChanged = QtCore.pyqtSignal(object)
class TimerRunnable(QtCore.QRunnable):
def __init__(self):
super().__init__()
self._signaller = Signaller()
@property
def signaller(self):
return self._signaller
def run(self):
print("secondary thread:", threading.current_thread())
time.sleep(0.5)
r = random.choice(("hello", (1, 2, 3), "key": "value"))
print("send:", r)
if not sip.isdeleted(self.signaller):
self.signaller.dataChanged.emit(r)
class Widget(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.text_edit = QtWidgets.QTextEdit()
self.setCentralWidget(self.text_edit)
timer = QtCore.QTimer(self, timeout=self.on_timeout, interval=1000)
timer.start()
@QtCore.pyqtSlot()
def on_timeout(self):
runnable = TimerRunnable()
runnable.signaller.dataChanged.connect(self.on_data_changed)
QtCore.QThreadPool.globalInstance().start(runnable)
@QtCore.pyqtSlot(object)
def on_data_changed(self, data):
text = json.dumps(data)
self.text_edit.append(text)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
print("main thread:", threading.current_thread())
sys.exit(app.exec_())
【讨论】:
我明白你的意思,但是如果我在主 GUI 线程中有多个计时器,这不会降低它的响应能力吗? @Giuseppe QTimer 只有一个 在本例中是。但是,如果我有其他计时器更新 GUI 的不同部分,这不会成为问题吗? @Giuseppe QTimers 不会产生开销,您有多少个 QTImer? @Giuseppe mmm,plop,4 个 QTimer 不会产生开销。每个 QTimer 都使用事件循环来查看是否到了触发信号的时间。一般来说,信号使用事件循环,它们不排队。以上是关于QRunnable 中的计时器的主要内容,如果未能解决你的问题,请参考以下文章