今回は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()
実際に動かしてみたものがこちらです。