以下のQtのstartTimerによるEventCallback挙動確認時のメモ
PySide2.QtCore.QObject.startTimer(interval[, timerType=Qt.CoarseTimer])
仕様には特に本件について何か書いているわけではなさそうだ、、
実動作として、timer event callback頻度は1msec周期にしつつ、event処理の中で1000msec sleepを入れてみる。
# !/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import time
import datetime
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import Qt, QObject
class MyObject(QObject):
def __init__(self, parent):
QObject.__init__(self, parent)
self.startTimer(1) # 1-millisecond timer
#self.startTimer(50) # 50-millisecond timer
#self.startTimer(100) # 1000-millisecond timer
#self.startTimer(1000) # 1-second timer
#self.startTimer(60000) # 1-minute timer
def timerEvent(self, event):
print("Timer ID:", event.timerId())
print("datetime now:", datetime.datetime.now())
time.sleep(1)
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.myobject = MyObject(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
実行したところ、1000msec間隔でevent処理が実行されているようにみえる。
どうやらevent処理中(今回の場合だと、1000msec sleep処理中)は、次のevent callback処理が呼び出されない様子?とりあえず現状動作としてこうだったという事をメモしておく。
$ python test.py
Timer ID: 1
datetime now: 2022-01-09 18:00:46.863970
Timer ID: 1
datetime now: 2022-01-09 18:00:47.866091
Timer ID: 1
datetime now: 2022-01-09 18:00:48.875696
Timer ID: 1
datetime now: 2022-01-09 18:00:49.914547
Timer ID: 1
datetime now: 2022-01-09 18:00:50.921863
Timer ID: 1
datetime now: 2022-01-09 18:00:51.922785
Timer ID: 1
datetime now: 2022-01-09 18:00:52.924472
追記
@tenmyoさんコメントの通り、以下にTimersに関する記載がありました。
Timers | Qt Core 6.2.2
https://doc.qt.io/qt-6/timers.html
For this mechanism to work, the application must run in an event loop.
You start an event loop with QApplication::exec(). When a timer fires,
the application sends a QTimerEvent, and the flow of control leaves
the event loop until the timer event is processed. This implies that a
timer cannot fire while your application is busy doing something else.
In other words: the accuracy of timers depends on the granularity of
your application.
特に以下が気になりイベントループを2つ実行したところ、同じイベントループの他処理に影響しました。
イベントループ内で時間の掛かる処理は別スレッドにするか、別のtimer処理に分ける等、設計する場合は考慮が必要だと思いました。
This implies that a
timer cannot fire while your application is busy doing something else.
In other words: the accuracy of timers depends on the granularity of
your application.
以下の通りMyObjectを2つにしたところ
# !/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import time
import datetime
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import Qt, QObject
class MyObject(QObject):
def __init__(self, parent):
QObject.__init__(self, parent)
self.startTimer(1) # 1-millisecond timer
#self.startTimer(50) # 50-millisecond timer
#self.startTimer(100) # 1000-millisecond timer
#self.startTimer(1000) # 1-second timer
#self.startTimer(60000) # 1-minute timer
def timerEvent(self, event):
print("Timer ID:", event.timerId()," datetime now:", datetime.datetime.now())
time.sleep(1)
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.myobject = MyObject(self)
self.myobject2 = MyObject(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
1000msec
毎にTimer ID: 1のtimerEvent
、Timer ID: 2のtimerEvent
、、が順番に返ってきました。
$ python qt.py
Timer ID: 1 datetime now: 2022-01-09 23:14:21.350370
Timer ID: 2 datetime now: 2022-01-09 23:14:22.351786
Timer ID: 1 datetime now: 2022-01-09 23:14:23.353236
Timer ID: 2 datetime now: 2022-01-09 23:14:24.354172
Timer ID: 1 datetime now: 2022-01-09 23:14:25.367485
Timer ID: 2 datetime now: 2022-01-09 23:14:26.367732
参考
PySide2.QtCore.QObject.startTimer(interval[, timerType=Qt.CoarseTimer])