プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2023/03/28

[PySide] QTimer の使い方

event_note2023/03/28 0:03

スレッドを使わずに定期的に GUI を更新するために、QTimer の使い方と挙動について簡単に調べてみました。

環境

  • Python 3.8.10
  • PySide 6.2.2.1

サンプルコード

import sys
import time
from datetime import datetime
from PySide6.QtCore import (QTimer, Signal)
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel)


class MainWindow(QWidget):
    """メインウィンドウ
    """

    countup = Signal(int)

    def __init__(self, parent=None):
        super().__init__(parent)

        self.__count = 0

        layout = QVBoxLayout()
        self.__label = QLabel(self.__current_count())
        layout.addWidget(self.__label)
        self.setLayout(layout)

        self.__timer = QTimer(self)
        self.__timer.timeout.connect(self.__timeout)
        self.__timer.start(1000)
        self.__timer.singleShot(10000, self.__single_shot1)
        self.__timer.singleShot(15000, self.__single_shot2)

    def __timeout(self):

        self.__count += 1
        print(f'{datetime.now()}, {self.__count}')
        self.__label.setText(self.__current_count())
        #time.sleep(3)

    def __current_count(self) -> str:
        return f'現在のカウント: {self.__count}'

    def __single_shot1(self):
        print(f'{datetime.now()}, 10秒経過')

    def __single_shot2(self):
        print(f'{datetime.now()}, 15秒経過')

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    ret = app.exec()
    sys.exit(ret)
2023-03-27 14:04:40.166652, 1
2023-03-27 14:04:41.115886, 2
2023-03-27 14:04:42.066937, 3
2023-03-27 14:04:43.026873, 4
2023-03-27 14:04:44.026648, 5
2023-03-27 14:04:45.026877, 6
2023-03-27 14:04:46.026574, 7
2023-03-27 14:04:47.026898, 8
2023-03-27 14:04:48.026477, 9
2023-03-27 14:04:49.027008, 10秒経過
2023-03-27 14:04:49.027169, 10
2023-03-27 14:04:50.027045, 11
2023-03-27 14:04:51.026868, 12
2023-03-27 14:04:52.027034, 13
2023-03-27 14:04:53.026916, 14
2023-03-27 14:04:54.026824, 15秒経過
2023-03-27 14:04:54.027010, 15

処理に時間がかかった場合はどうなる?

上記のコードでは、1秒ごとに __timeout 関数が実行されますが、もしその中で処理に時間がかかったとしたらどうなるか?
試しに3秒のスリープを入れてみました(上記のコメントアウトを解除)。

2023-03-27 14:07:10.458991, 1
2023-03-27 14:07:13.462465, 2
2023-03-27 14:07:16.464238, 3
2023-03-27 14:07:19.467192, 4
2023-03-27 14:07:22.470589, 10秒経過
2023-03-27 14:07:22.471410, 5
2023-03-27 14:07:25.475184, 6
2023-03-27 14:07:28.478740, 15秒経過
2023-03-27 14:07:28.480526, 7
2023-03-27 14:07:31.484492, 8

3秒経過後、すぐに __timeout がコールされています。
前の処理が完了しないと次の処理は行われないようです。