【PySimpleGUI】タイムアウト(timeout)を使って一定時間毎に処理を行う方法[Python]

  • URLをコピーしました!
目次

PySimpleGUI

前回、PySimpleGUIでpng画像、jpg画像を表示する方法を紹介しました。

今回はPySimpleGUIのタイムアウト(timeout)を使って一定時間毎に処理を行う方法を紹介します。

PySimpleGUIではキーボード入力などを「While文」を使って待ち、入力されたらそれに対応する処理を行うようになっています。

そのためさらに内部で「While文」を使ってもループ内部の処理は行われません。

つまりこれは動きません。

import PySimpleGUI as sg
import time

layout=[[sg.Text("1", font=("Arial", 30), key="-text-")]]
flag = 1

window=sg.Window("",layout, size=(200, 100))

while True:
    event,values=window.read()
    if event == sg.WIN_CLOSED:
        break
    while True:
        if flag == 1:
            window["-text-"].update("2")
            flag = 2
            time.sleep(1)
        elif flag == 2:
            window["-text-"].update("1")
            flag = 1
            time.sleep(1)

window.close()

それなら入力をした後にWhile文でループさせようとこんなプログラムにしても動きません。

import PySimpleGUI as sg
import time

layout=[[sg.Text("1", font=("Arial", 30), key="-text-")]]
flag = 1

window=sg.Window("",layout, size=(200, 100), return_keyboard_events=True)

while True:
    event,values=window.read()
    if event == sg.WIN_CLOSED:
        break
    elif event == "1":
        while True:
            if flag == 1:
                window["-text-"].update("2")
                flag = 2
                time.sleep(1)
            elif flag == 2:
                window["-text-"].update("1")
                flag = 1
                time.sleep(1)

window.close()

ではどうするか?の答えがタイムアウト(timeout)を使って入力待ち後の処理を強制的に行うという方法です。

それでは始めていきましょう。

タイムアウトを使って一定時間毎に処理を行う方法

タイムアウトを使うにはwindwo.readに「timeout=ミリ秒」と「timeout_key=”タイムアウトのキー”」を追加します。

そしてタイムアウトした際の処理を「if event == “-timeout-“:」の下に記述します。

ということでこんな感じです。

import PySimpleGUI as sg

layout=[[sg.Text("1", font=("Arial", 30), key="-text-")]]

window=sg.Window("",layout, size=(200, 100))

flag = 1

while True:
    event,values=window.read(timeout=1000, timeout_key="-timeout-")
    if event == sg.WIN_CLOSED:
        break
    elif event == "-timeout-":
        if flag == 1:
            window["-text-"].update("2")
            flag = 2
        elif flag == 2:
            window["-text-"].update("1")
            flag = 1

window.close()

このプログラムでは1000ミリ秒、つまり1秒毎に表示されている数字が「1」と「2」に変化します。

処理時間を制御する方法

上記の方法では処理が終わってから指定時間(上記の例では1000ミリ秒)待ち、次の処理が行われます。

つまり1サイクルの時間は「指定時間+処理時間」となります。

例えばこちらのプログラムのように処理中で「time.sleep」を入れると1回のサイクルの時間が指定時間だけでないことがわかります。

import PySimpleGUI as sg
import time

layout=[[sg.Text("1", font=("Arial", 30), key="-text-")]]

window=sg.Window("",layout, size=(200, 100))

flag = 1
time1 = time.time()

while True:
    event,values=window.read(timeout=1000, timeout_key="-timeout-")
    if event == sg.WIN_CLOSED:
        break
    elif event == "-timeout-":
        time2 = time.time()
        print(time2 - time1)
        if flag == 1:
            window["-text-"].update("2")
            flag = 2
        elif flag == 2:
            window["-text-"].update("1")
            flag = 1
        time1 = time.time()
        time.sleep(0.5)

window.close()

実行結果
1.2369978427886963
1.5092718601226807
1.5102410316467285
1.5122461318969727
1.5109450817108154
1.5144672393798828
(以下略)

もしなるべく処理の時間を一定にしたい場合は「timeモジュール」を使って時間を測って、その時間に対して処理を行うかどうかを判断するという方法があります。

import PySimpleGUI as sg
import time

time_step = 1

layout=[[sg.Text("1", font=("Arial", 30), key="-text-")]]

window=sg.Window("",layout, size=(200, 100))

flag = 1
time1 = time.time()

while True:
    event,values=window.read(timeout=10, timeout_key="-timeout-")
    if event == sg.WIN_CLOSED:
        break
    elif event == "-timeout-":
        time2 = time.time()
        if time2 - time1 >= time_step:
            print(time2 - time1)
            if flag == 1:
                window["-text-"].update("2")
                flag = 2
            elif flag == 2:
                window["-text-"].update("1")
                flag = 1
            time1 = time.time()
            time.sleep(0.5)
            
window.close()

実行結果
1.0153701305389404
1.0081090927124023
1.0012989044189453
1.0079469680786133
1.001964807510376
1.00689697265625
(以下略)

この例ではWhile文に入る前に「time1 = time.time()」で1つ目の時間を取得しています。

そしてタイムアウトの処理の中で「time2 = time.time()」として2つ目の時間を取得しています。

このこの2つの時間を引き算し、1サイクルの処理時間(ここではtime_step)と比較し、条件に合った場合のみ(if time2 – time1 >= time_step:)、その後の処理がされるようにしています。

また処理がされた場合には「time1 = time.time()」として1つ目の時間を取得しなおします。

また重要な点としてタイムアウトの秒数は1サイクルの時間に対して十分短い時間(ここでは10ミリ秒)にすることです。

これで今回の場合は1サイクルがほぼ1秒にすることができました。

このテクニックはPySimpleGUIだけでなく、処理の時間を一定にしたい場合に有用なので覚えておくといいと思います。

次回はPythonのグラフィックライブラリであるTurtleを使ってお絵描きをする方法を紹介していきます。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次