Tkinterでストップウォッチアプリを作ってみよう

Tkinterでストップウォッチアプリを作ってみよう

今回はTkinterを使ってGUIのストップウォッチアプリを作成してみましょう。ストップウォッチは機能がシンプルでわかりやすいため初心者でも作りやすく、timeモジュールのちょっとした応用やafterメソッドによるリアルタイム処理を学ぶことができます。

目次

必要なウィジェットを表示

まずは必要になるウィジェットを画面に表示してみましょう。

import tkinter as tk
import time

 # tk.Frameを継承したApplicationクラスを作成
class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # ウィンドウの設定
        master.title("ストップウォッチ")
        master.geometry("400x160")

        # 変数定義
        self.startTime = 0.0 # 開始時間
        self.elapsedTime = 0.0 # 経過時間

        # 実行内容
        self.pack()
        self.create_widget()

    # create_widgetメソッドを定義
    def create_widget(self):

        # canvasウィジェットを作成
        self.canvas = tk.Canvas(self.master, width=380, height=80, bg="lightgreen")
        self.canvas.place(x=10, y=10)
        # 経過時間を表示
        self.canvas.create_text(380,40,text=round(self.elapsedTime,1), font=("MSゴシック体", "24", "bold"), tag="Time", anchor="e")

        #スタートボタン
        startButton = tk.Button(self.master, text="スタート", font=("MSゴシック体", "18","bold"))
        startButton.place(x=10, y=100)
        #ストップボタン
        stopButton = tk.Button(self.master, text="ストップ", font=("MSゴシック体", "18","bold"))
        stopButton.place(x=140, y=100)
        #リセットボタン
        resetButton = tk.Button(self.master, text="リセット", font=("MSゴシック体", "18","bold"))
        resetButton.place(x=270, y=100)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master=root)
    app.mainloop()

ストップウォッチなので開始時間と経過時間の変数が必要となることはわかっています。14~15行目で定義しています。

24~38行目で次のウィジェットを作成・配置しています。

  • 時間を表示するためのキャンバス
  • スタートボタン
  • ストップボタン
  • リセットボタン
必要なウィジェットを表示

まだウィジェットを表示させただけなので動作はしません。

これに機能(処理)を書き加えていきましょう。

スタートボタンの処理

まずはスタートボタンです。

押すと時間の計測が開始され、それがリアルタイムで画面に表示され続けるよう処理を書いてみましょう。

        # 変数定義
        self.after_id = 0 # after_id変数を定義

        #中略

        #スタートボタン
        #押した時にstartButtonClicked関数が実行されるよう記述
        startButton = tk.Button(self.master, text="スタート", font=("MSゴシック体", "18","bold"), command=self.startButtonClicked)
        startButton.place(x=10, y=100)

    # スタートボタンが押された時の処理
    def startButtonClicked(self):
        self.startTime = time.time() - self.elapsedTime # startTime変数に開始時間を代入
        self.updateTime() # updateTime関数を実行

    # 表示時間の更新処理
    def updateTime(self):
        self.canvas.delete("Time") # 表示時間を消去
        self.elapsedTime = time.time() - self.startTime # 経過時間を代入
        self.canvas.create_text(380,40,text=round(self.elapsedTime,1),font=("MSゴシック体","24","bold"),tag="Time",anchor="e") # 経過時間を表示
        self.after_id = self.after(10, self.updateTime)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master=root)
    app.mainloop()

comanndオプションでスタートボタンが押された時にstartButtonClicked関数が呼び出されるように記述。

startButtonClicked関数の中で現在の時刻の取得と、updateTime関数を実行するよう記述しています。

このupdateTime関数が今回のキモです。

  • 表示時間を一旦消去
  • 経過時間を計算して代入
  • 時間を表示

という処理を行った後、afterメソッドでupdateTime関数が再帰的に呼び出されるようにしています。

こうすることで一度スタートボタンを押した後は表示時間がリアルタイムで更新され続けることになります。

また、その際にafterメソッドの返り値をafter_id変数に保存しています。

スタートボタンの処理

ストップボタンの処理

次はストップボタンです。

        # ストップボタン
        stopButton = tk.Button(self.master, text="ストップ", font=("MSゴシック体", "18","bold"), command=self.stopButtonClicked)
        stopButton.place(x=140, y=100)

    # 中略

    # ストップボタンが押された時の処理
    def stopButtonClicked(self):
        self.after_cancel(self.after_id) # updateTime関数の再帰処理を終了

こちらもcomanndオプションでstopButtonClicked関数を指定します。

stopButtonClicked関数の中身はafter_cancelメソッドを使ってupdateTime関数の再帰処理を停止するだけです。

リセットボタンの処理

最後にリセットボタンです。

計測時間を0にリセットします。

        # リセットボタン
        resetButton = tk.Button(self.master, text="リセット", font=("MSゴシック体", "18","bold"), command=self.resetButtonClicked)
        resetButton.place(x=270, y=100)

        # 中略

        # リセットボタンが押された時の処理
    def resetButtonClicked(self):
        self.startTime = time.time() # startTime変数に現在時刻を代入
        self.elapsedTime = 0.0 # elapsedTime変数を初期化
        self.canvas.delete("Time") # 表示時間を消去
        self.canvas.create_text(380,40,text=round(self.elapsedTime,1),font=("MSゴシック体","24","bold"),tag="Time",anchor="e") # 時間0.0を表示 

こちらもcomanndオプションでresetButtonClicked関数を指定。

resetButtonClicked関数で開始時間と計測時間を0にして画面に表示する処理を行います。

完成

今回作成したストップウォッチアプリのソースコードです。

import tkinter as tk
import time

 # tk.Frameを継承したApplicationクラスを作成
class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # ウィンドウの設定
        master.title("ストップウォッチ")
        master.geometry("400x160")

        # 変数定義
        self.startTime = 0.0 # 開始時間
        self.elapsedTime = 0.0 # 経過時間
        self.after_id = 0 # after_id変数を定義

        # 実行内容
        self.pack()
        self.create_widget()

    # create_widgetメソッドを定義
    def create_widget(self):

        # canvasウィジェットを作成
        self.canvas = tk.Canvas(self.master, width=380, height=80, bg="lightgreen")
        self.canvas.place(x=10, y=10)
        self.canvas.create_text(380,40,text=round(self.elapsedTime,1), font=("MSゴシック体", "24", "bold"), tag="Time", anchor="e") # 時間0.0を表示

        # ボタンを作成・配置
        startButton = tk.Button(self.master, text="スタート", font=("MSゴシック体", "18","bold"), command=self.startButtonClicked)
        startButton.place(x=10, y=100)

        stopButton = tk.Button(self.master, text="ストップ", font=("MSゴシック体", "18","bold"), command=self.stopButtonClicked)
        stopButton.place(x=140, y=100)

        resetButton = tk.Button(self.master, text="リセット", font=("MSゴシック体", "18","bold"), command=self.resetButtonClicked)
        resetButton.place(x=270, y=100)

    # 各ボタンが押された時の処理
    def startButtonClicked(self):
        self.startTime = time.time() - self.elapsedTime # startTime変数に開始時間を代入
        self.updateTime() # updateTime関数を実行

    def stopButtonClicked(self):
        self.after_cancel(self.after_id) # updateTime関数の再帰処理を終了

    def resetButtonClicked(self):
        self.startTime = time.time() # startTime変数に現在時刻を代入
        self.elapsedTime = 0.0 # elapsedTime変数を初期化
        self.canvas.delete("Time") # 表示時間を消去
        self.canvas.create_text(380,40,text=round(self.elapsedTime,1),font=("MSゴシック体","24","bold"),tag="Time",anchor="e") # 時間0.0を表示

    # 表示時間の更新処理
    def updateTime(self):
        self.canvas.delete("Time") # 表示時間を消去
        self.elapsedTime = time.time() - self.startTime # 経過時間を代入
        self.canvas.create_text(380,40,text=round(self.elapsedTime,1),font=("MSゴシック体","24","bold"),tag="Time",anchor="e") # 経過時間を表示
        self.after_id = self.after(10, self.updateTime)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master=root)
    app.mainloop()
完成

実際に動かしてみたものがこちらです。

このエントリーをはてなブックマークに追加

コメントを残す

頂いたコメントは一読した後表示させて頂いております。
反映まで数日かかる場合もございますがご了承下さい。