Python 如何更改Qthread内Qtimer的间隔?
我希望能够在QThread内部更改QTimer的间隔时间。这是我的密码Python 如何更改Qthread内Qtimer的间隔?,python,pyqt,pyqt5,qthread,qtimer,Python,Pyqt,Pyqt5,Qthread,Qtimer,我希望能够在QThread内部更改QTimer的间隔时间。这是我的密码 import sys from PyQt5 import QtWidgets from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.QtCore import QObject, QTimer, QThread class Worker(QObject): def __init__(self): QObject.__init
import sys
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QObject, QTimer, QThread
class Worker(QObject):
def __init__(self):
QObject.__init__(self)
self.timer = QTimer(self)
self.timer.timeout.connect(self.work)
def start(self):
self.timer.start(1000)
def work(self):
print("Hello World...")
def set_interval(self, interval):
self.timer.setInterval(interval)
def main():
# Set up main window
app = QApplication(sys.argv)
win = QMainWindow()
win.setFixedSize(200, 100)
spinbox_interval = QtWidgets.QSpinBox(win)
spinbox_interval.setMaximum(5000)
spinbox_interval.setSingleStep(500)
spinbox_interval.setValue(1000)
worker = Worker()
thread = QThread()
worker.moveToThread(thread)
thread.started.connect(worker.start)
thread.start()
def change_interval():
value = spinbox_interval.value()
worker.set_interval(value)
spinbox_interval.valueChanged.connect(change_interval)
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
如果在启动计时器后调用worker.setInterval(),则超时信号不再发出信号。有人能解释一下我做错了什么吗 要了解问题,必须在控制台/CMD中运行以获取错误消息,从而了解原因,如果执行此操作,则会得到以下错误消息:
QObject::killTimer: Timers cannot be stopped from another thread
QObject::startTimer: Timers cannot be started from another thread
要理解此错误消息,您必须知道:
- QObject不是线程安全的,因此不能从其他线程修改它们
- QObject的子对象与父对象生活在同一线程中
带pyqtSlot:QMetaObject.invokeMethod()
import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox from PyQt5.QtCore import pyqtSlot, QMetaObject, QObject, Qt, QTimer, QThread, Q_ARG class Worker(QObject): def __init__(self): QObject.__init__(self) self.timer = QTimer(self) self.timer.timeout.connect(self.work) def start(self): self.timer.start(1000) def work(self): print("Hello World...") @pyqtSlot(int) def set_interval(self, interval): self.timer.setInterval(interval) def main(): # Set up main window app = QApplication(sys.argv) win = QMainWindow() win.setFixedSize(200, 100) spinbox_interval = QSpinBox(win) spinbox_interval.setMaximum(5000) spinbox_interval.setSingleStep(500) spinbox_interval.setValue(1000) worker = Worker() thread = QThread() worker.moveToThread(thread) thread.started.connect(worker.start) thread.start() def change_interval(): value = spinbox_interval.value() QMetaObject.invokeMethod( worker, "set_interval", Qt.QueuedConnection, Q_ARG(int, value) ) spinbox_interval.valueChanged.connect(change_interval) win.show() ret = app.exec_() QMetaObject.invokeMethod(worker.timer, "stop") thread.quit() thread.wait() sys.exit(ret) if __name__ == "__main__": main()
- 带有插槽的自定义信号:
import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox from PyQt5.QtCore import pyqtSignal, pyqtSlot, QMetaObject, QObject, Qt, QTimer, QThread class Worker(QObject): updateInterval = pyqtSignal(int) def __init__(self): QObject.__init__(self) self.timer = QTimer(self) self.timer.timeout.connect(self.work) self.updateInterval.connect(self.set_interval) def start(self): self.timer.start(1000) def work(self): print("Hello World...") @pyqtSlot(int) def set_interval(self, interval): self.timer.setInterval(interval) def main(): # Set up main window app = QApplication(sys.argv) win = QMainWindow() win.setFixedSize(200, 100) spinbox_interval = QSpinBox(win) spinbox_interval.setMaximum(5000) spinbox_interval.setSingleStep(500) spinbox_interval.setValue(1000) worker = Worker() thread = QThread() worker.moveToThread(thread) thread.started.connect(worker.start) thread.start() def change_interval(): value = spinbox_interval.value() worker.updateInterval.emit(value) spinbox_interval.valueChanged.connect(change_interval) win.show() ret = app.exec_() QMetaObject.invokeMethod(worker.timer, "stop") thread.quit() thread.wait() sys.exit(ret) if __name__ == "__main__": main()
- 自定义QEvent:
import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox from PyQt5.QtCore import QEvent, QMetaObject, QObject, Qt, QTimer, QThread class IntervalEvent(QEvent): def __init__(self, interval): QEvent.__init__(self, QEvent.User + 1000) self._interval = interval @property def interval(self): return self._interval class Worker(QObject): def __init__(self): QObject.__init__(self) self.timer = QTimer(self) self.timer.timeout.connect(self.work) def start(self): self.timer.start(1000) def work(self): print("Hello World...") def set_interval(self, interval): self.timer.setInterval(interval) def event(self, e): if isinstance(e, IntervalEvent): self.set_interval(e.interval) return Worker.event(self, e) def main(): # Set up main window app = QApplication(sys.argv) win = QMainWindow() win.setFixedSize(200, 100) spinbox_interval = QSpinBox(win) spinbox_interval.setMaximum(5000) spinbox_interval.setSingleStep(500) spinbox_interval.setValue(1000) worker = Worker() thread = QThread() worker.moveToThread(thread) thread.started.connect(worker.start) thread.start() def change_interval(): value = spinbox_interval.value() event = IntervalEvent(value) QApplication.postEvent(worker, event) spinbox_interval.valueChanged.connect(change_interval) win.show() ret = app.exec_() QMetaObject.invokeMethod(worker.timer, "stop") thread.quit() thread.wait() sys.exit(ret) if __name__ == "__main__": main()
与QTimer.singleShot()
(仅适用于PyQt5,不适用于PySide2)functools.partial()
QObject::killTimer: Timers cannot be stopped from another thread
QObject::startTimer: Timers cannot be started from another thread
要理解此错误消息,您必须知道:
- QObject不是线程安全的,因此不能从其他线程修改它们
- QObject的子对象与父对象生活在同一线程中
带pyqtSlot:QMetaObject.invokeMethod()
import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox from PyQt5.QtCore import pyqtSlot, QMetaObject, QObject, Qt, QTimer, QThread, Q_ARG class Worker(QObject): def __init__(self): QObject.__init__(self) self.timer = QTimer(self) self.timer.timeout.connect(self.work) def start(self): self.timer.start(1000) def work(self): print("Hello World...") @pyqtSlot(int) def set_interval(self, interval): self.timer.setInterval(interval) def main(): # Set up main window app = QApplication(sys.argv) win = QMainWindow() win.setFixedSize(200, 100) spinbox_interval = QSpinBox(win) spinbox_interval.setMaximum(5000) spinbox_interval.setSingleStep(500) spinbox_interval.setValue(1000) worker = Worker() thread = QThread() worker.moveToThread(thread) thread.started.connect(worker.start) thread.start() def change_interval(): value = spinbox_interval.value() QMetaObject.invokeMethod( worker, "set_interval", Qt.QueuedConnection, Q_ARG(int, value) ) spinbox_interval.valueChanged.connect(change_interval) win.show() ret = app.exec_() QMetaObject.invokeMethod(worker.timer, "stop") thread.quit() thread.wait() sys.exit(ret) if __name__ == "__main__": main()
- 带有插槽的自定义信号:
import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox from PyQt5.QtCore import pyqtSignal, pyqtSlot, QMetaObject, QObject, Qt, QTimer, QThread class Worker(QObject): updateInterval = pyqtSignal(int) def __init__(self): QObject.__init__(self) self.timer = QTimer(self) self.timer.timeout.connect(self.work) self.updateInterval.connect(self.set_interval) def start(self): self.timer.start(1000) def work(self): print("Hello World...") @pyqtSlot(int) def set_interval(self, interval): self.timer.setInterval(interval) def main(): # Set up main window app = QApplication(sys.argv) win = QMainWindow() win.setFixedSize(200, 100) spinbox_interval = QSpinBox(win) spinbox_interval.setMaximum(5000) spinbox_interval.setSingleStep(500) spinbox_interval.setValue(1000) worker = Worker() thread = QThread() worker.moveToThread(thread) thread.started.connect(worker.start) thread.start() def change_interval(): value = spinbox_interval.value() worker.updateInterval.emit(value) spinbox_interval.valueChanged.connect(change_interval) win.show() ret = app.exec_() QMetaObject.invokeMethod(worker.timer, "stop") thread.quit() thread.wait() sys.exit(ret) if __name__ == "__main__": main()
- 自定义QEvent:
import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox from PyQt5.QtCore import QEvent, QMetaObject, QObject, Qt, QTimer, QThread class IntervalEvent(QEvent): def __init__(self, interval): QEvent.__init__(self, QEvent.User + 1000) self._interval = interval @property def interval(self): return self._interval class Worker(QObject): def __init__(self): QObject.__init__(self) self.timer = QTimer(self) self.timer.timeout.connect(self.work) def start(self): self.timer.start(1000) def work(self): print("Hello World...") def set_interval(self, interval): self.timer.setInterval(interval) def event(self, e): if isinstance(e, IntervalEvent): self.set_interval(e.interval) return Worker.event(self, e) def main(): # Set up main window app = QApplication(sys.argv) win = QMainWindow() win.setFixedSize(200, 100) spinbox_interval = QSpinBox(win) spinbox_interval.setMaximum(5000) spinbox_interval.setSingleStep(500) spinbox_interval.setValue(1000) worker = Worker() thread = QThread() worker.moveToThread(thread) thread.started.connect(worker.start) thread.start() def change_interval(): value = spinbox_interval.value() event = IntervalEvent(value) QApplication.postEvent(worker, event) spinbox_interval.valueChanged.connect(change_interval) win.show() ret = app.exec_() QMetaObject.invokeMethod(worker.timer, "stop") thread.quit() thread.wait() sys.exit(ret) if __name__ == "__main__": main()
与QTimer.singleShot()
(仅适用于PyQt5,不适用于PySide2)functools.partial()