PySide超入門【第22回 | 応用編】時計・カウンター・プログレスバーを作ろう!QTimer徹底解説

\ 迷ったらまずTechAcademyの無料カウンセリング! /

GUIアプリケーションを作るときに「一定間隔で処理を実行したい」「自動的に画面を更新したい」という場面はよくあります。
例えば「時計アプリで1秒ごとに時間を更新する」「ゲームでキャラクターを動かす」「センサー値を定期的に取得する」などです。

そんなときに活躍するのが QTimer クラスです。
QTimerは指定した間隔でシグナル(timeout)を発行することで、イベントループに非同期的な処理を追加する仕組みを提供します。

今回の記事では QTimerの基本コードから、主要プロパティ・メソッドの解説、よくある質問まで まとめていきます。

目次

QTimerとは?

QTimerは「一定間隔ごとに処理を実行する仕組み」を提供するクラスです。

基本コード

このサンプルコードでは、QTimer(タイマー機能)を使ってできることを3つまとめて紹介しています。

  • 時計 … 今の時刻を1秒ごとに表示します。
  • 🔢 カウンター … 数字をカウントアップしていきます。
  • 📊 プログレスバー … バーを少しずつ動かして「進み具合」を見せます。

それぞれの機能は別々の関数に分けて書いているので、どこを直せばいいのかがすぐに分かります。
「時計だけ使いたい!」という場合も、このコードをベースにすればすぐに自分のアプリに取り入れられます

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


class TimerDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QTimerデモ: 時計・カウンター・プログレスバー")
        self.resize(400, 200)

        # メインレイアウト
        layout = QVBoxLayout(self)

        # 時計エリア
        self.clock_label = QLabel("時計: --:--:--")
        layout.addWidget(self.create_clock_widget())

        # カウンターエリア
        self.counter_label = QLabel("カウンター: 0")
        layout.addWidget(self.create_counter_widget())

        # プログレスバーエリア
        self.progress = QProgressBar()
        layout.addWidget(self.create_progress_widget())

        # 各機能を開始
        self.start_clock()
        self.start_counter()
        self.start_progress()

    # ---------- 時計 ----------
    def create_clock_widget(self):
        w = QWidget()
        box = QHBoxLayout(w)
        box.addWidget(self.clock_label)
        return w

    def start_clock(self):
        self.clock_timer = QTimer()
        self.clock_timer.timeout.connect(self.update_clock)
        self.clock_timer.start(1000)

    def update_clock(self):
        self.clock_label.setText(
            "時計: " + datetime.datetime.now().strftime("%H:%M:%S")
        )

    # ---------- カウンター ----------
    def create_counter_widget(self):
        w = QWidget()
        box = QHBoxLayout(w)
        box.addWidget(self.counter_label)
        return w

    def start_counter(self):
        self.count = 0
        self.counter_timer = QTimer()
        self.counter_timer.timeout.connect(self.update_counter)
        self.counter_timer.start(500)

    def update_counter(self):
        self.count += 1
        self.counter_label.setText(f"カウンター: {self.count}")

    # ---------- プログレスバー ----------
    def create_progress_widget(self):
        w = QWidget()
        box = QHBoxLayout(w)
        box.addWidget(self.progress)
        return w

    def start_progress(self):
        self.value = 0
        self.progress_timer = QTimer()
        self.progress_timer.timeout.connect(self.update_progress)
        self.progress_timer.start(100)

    def update_progress(self):
        self.value += 1
        if self.value > 100:
            self.progress_timer.stop()
        self.progress.setValue(self.value)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TimerDemo()
    window.show()
    sys.exit(app.exec())

主なプロパティとメソッド一覧(全解説)

Noメソッド / プロパティ説明
1setInterval(int msec)繰り返し間隔を設定します。timer.setInterval(2000)
2timeout (シグナル)設定時間ごとに発火するシグナル。timer.timeout.connect(func)
3start(int msec)タイマーを開始します。msecはミリ秒単位。timer.start(1000)
4stop()タイマーを停止します。timer.stop()
5isActive()タイマーが動作中か判定します。print(timer.isActive())
6remainingTime()次の timeout までの残り時間を取得します。print(timer.remainingTime())
7setSingleShot(bool) / isSingleShot()一度だけ発火する設定にする/設定を確認する。timer.setSingleShot(True) print(timer.isSingleShot())
8interval()現在の間隔(ミリ秒)を取得します。print(timer.interval())
9timerId()内部タイマーIDを返しますprint(timer.timerId())
10QTimer.singleShot(int, callable)1回だけ処理を遅延実行する便利メソッド。QTimer.singleShot(3000, func)

各プロパティ・メソッド 詳細解説

【1】タイマーの発火間隔を設定

概要:タイマーの発火間隔をミリ秒単位で設定します。
メソッドsetInterval(ms)
使い方(時計で使用)

def start_clock(self):
    self.clock_timer.setInterval(2000) # 2秒ごとにtimeoutが発火
    self.clock_timer.start()

⏰ 時計アプリではstart関数の引数で設定しています。

【2】シグナル

概要:設定した間隔ごとに発火し、登録された関数を実行します。
シグナルtimeout
使い方(時計・カウンター・プログレスバーで共通)

self.clock_timer.timeout.connect(self.update_clock)
self.counter_timer.timeout.connect(self.update_counter)
self.progress_timer.timeout.connect(self.update_progress)

🔑 今回のコードの心臓部!時計・カウンター・プログレスバーすべて、この timeout に更新処理をつなげています。

【3】タイマーを開始

概要:タイマーを開始します。引数を指定すると、その場で間隔を上書きできます。
メソッドstart()
使い方(カウンターで使用)

self.counter_timer.start()

▶️ 「スタートボタン」を押したらカウンターがカウントアップを開始。
プログレスバーでも同じように start() で動き出します。

【4】タイマーを停止

概要:タイマーを停止します。
メソッドstop()
使い方(プログレスバーで使用)

def update_progress(self):
    if self.value > 100:
        self.progress_timer.stop()

⏹ プログレスバーが100%に達したときに停止。
「時間制御」をする上で必ず覚えておきたいメソッドです。

【5】タイマーが動いているかどうか

概要:タイマーが現在動いているかどうかを確認します。
メソッドisActive()
使い方(応用例)

if self.counter_timer.isActive():
    print("カウンターは動作中です")

# カウンターは動作中です
# カウンターは動作中です
# ・・・

🔍 状態をチェックできるので、「動作中はボタンを無効化」 といった処理に使えます。

【6】次までの残り時間

概要:次に timeout が発火するまでの残り時間(ミリ秒)を返します。
メソッドremainingTime()
使い方(応用例)

print(self.progress_timer.remainingTime())
# 100
# 99

⏱ プログレスバーの「次の更新まであと何ミリ秒?」といった確認に使えます。

【7】ワンショットタイマーに設定

概要:一度だけ発火する「ワンショットタイマー」に設定できます。
メソッドsetSingleShot(True)
使い方(応用例)

def start_clock(self):
    self.clock_timer.setSingleShot(True)
    self.clock_timer.start(1000)

💡 「3秒だけメッセージを表示して消す」など、一度きりの処理に便利です。

【8】タイマー間隔

概要:現在のタイマー間隔(ミリ秒)を取得します。
メソッドinterval()
使い方(応用例)

print(self.clock_timer.interval())  
# 2000

📝 「このタイマーは何ミリ秒ごとに動作しているか?」を確認できます。
時計やカウンターで「間隔が正しく設定されているかデバッグ」するのに便利。

【9】タイマーの内部ID

概要:タイマーの内部ID(整数値)を返します。
メソッドtimerId()
使い方(応用例)

print(f'時計タイマー:{self.clock_timer.timerId()}')
print(f'カウンタータイマー:{self.counter_timer.timerId()}')
print(f'プログレスタイマー:{self.progress_timer.timerId()}')

# 時計タイマー:1
# カウンタータイマー:2
# プログレスタイマー:3

⚙️ 通常はあまり使いませんが、複数タイマーを低レベルAPIで管理するときに便利です。

【10】ワンショットタイマーの作成

概要:指定した時間後に一度だけ関数を呼び出す「ワンショットタイマー」を作ります。
静的メソッドQTimer.singleShot(ms, function)
使い方(応用例)

def __init__(self):
    QTimer.singleShot(3000, lambda: print("3秒後に実行!"))

# 3秒後に実行!

✨ 「3秒後にダイアログを閉じる」「一定時間後にメッセージを消す」といった処理で大活躍。
今回のコードには入っていませんが、アニメーションやユーザー操作の補助でよく使います。

よくある質問(FAQ)

sleep() を使ったらGUIが止まってしまいました。なぜ?

sleep() はイベントループをブロックするため、GUIがフリーズします。代わりに QTimer を使いましょう。

複数のQTimerを同時に動かせますか?

はい。独立したQTimerを作成すれば、それぞれが並行して動作します。

一度だけ処理を遅延実行したい場合はどうすればいい?

QTimer.singleShot(ms, func) を使うのが便利です。

精度は高いですか?

高精度ではありません。OSのイベントループに依存するため、数ms〜数十msの誤差が出る場合があります。

アニメーションとQTimerはどちらを使うべきですか?

単純に一定間隔で処理したいならQTimer、滑らかな動きを作りたいならQPropertyAnimationやQTimeLineが適しています。

まとめ

QTimer は、一定の間隔ごとに自動で処理を実行できる 非同期タイマー です。これを使うことで、GUIアプリケーションが止まることなく、時間に応じた処理を簡単に組み込むことができます。

基本的な使い方は、start(msec) でタイマーを開始し、timeout.connect(...) で処理したい関数を接続する方法です。例えば、1秒ごとに画面を更新したり、カウンターを進めたりする処理を簡単に実装できます。

また、setSingleShot(True)QTimer.singleShot(...) を使えば、一度だけ実行したい処理も簡単に書けます。例えば、アプリ起動後に1回だけメッセージを表示する、といった場面で便利です。

GUIアプリを作る上で、ユーザー操作をブロックせずに時間に応じた処理を行うには、QTimer の理解と活用が欠かせません。非同期処理の基礎として、ぜひ使いこなせるようにしましょう。

シェアしてくださると嬉しいです!
  • URLをコピーしました!

コメント

コメントする

目次