背景・目的
ランニングマシンでランニングをしているとき、ふと「5分や10分を区切りにして頑張ろう」と思うことがあります。実際に、その区切りが過ぎるまでは頑張ろうという意識が働き、走り続けることができるからです。
これなら、表示時間を短くし、実際の経過時間を長く設定することで、体感時間を短く感じさせ、実際にはより長く頑張ることができるのではないかと考えました。
そこで、「実際の経過時間と表示される時間が異なる」というイリュージョンタイマーを作成しようと思い立ちました。
完成イメージ
- 機能概要:
- 時間の設定(見かけ上の時間と実際の時間)
- 開始/停止/再開機能
- リセット機能
- タイマー終了時の通知機能
タイマーの仕様
設定時間と見かけ上の時間
このタイマーは、設定された「見かけ上の時間(表示される時間)」と、実際に経過している「実際の経過時間(実時間)」が異なる仕様です。
見かけ上の時間と実際の経過時間の算出方法
-
見かけ上の時間:
- ユーザーが設定した時間(例えば、
20分
)が見かけ上のタイマーに表示される時間として使用されます。
- ユーザーが設定した時間(例えば、
-
実際の経過時間:
- 実際には、ユーザーが設定した時間よりも長め(例えば、
30分
)の時間が実際に経過します。 - この差を
time_ratio
(時間比率)で計算します。 -
time_ratio
は以下の式で計算されます:例えば、time_ratio = 実際の経過時間 / 見かけ上の時間
見かけ上の時間
が20分
、実際の経過時間
が30分
の場合、time_ratio
は30 / 20 = 1.5
となります。
- 実際には、ユーザーが設定した時間よりも長め(例えば、
-
動作の仕組み:
- タイマーの内部では、実際の経過時間が
time_ratio
に基づいて更新されます。これにより、表示時間は短く(例えば、20分
)表示される一方で、実際の経過時間はその時間に対して1.5倍
(30分
)進行することになります。
- タイマーの内部では、実際の経過時間が
ソースコード全体
import tkinter as tk
from tkinter import ttk, messagebox
class IllusionTimerApp:
def __init__(self, root):
self.root = root
self.root.title("イリュージョンタイマー")
self.root.geometry("400x300")
self.illusion_time = tk.IntVar(value=20)
self.actually_time = tk.IntVar(value=30)
self.is_running = False
self.time_ratio = 1
self.remaining_seconds = 0
self.main_frame = ttk.Frame(self.root)
self.main_frame.place(relx=0.5, rely=0.5, anchor="center")
self.setup_gui()
self.reset_timer()
def setup_gui(self):
ttk.Label(self.main_frame, text="見かけ上の時間 (分):").grid(row=0, column=0, padx=5, pady=5, sticky="e")
ttk.Entry(self.main_frame, textvariable=self.illusion_time, width=5).grid(row=0, column=1, padx=5, pady=5)
ttk.Label(self.main_frame, text="実際の経過時間 (分):").grid(row=1, column=0, padx=5, pady=5, sticky="e")
ttk.Entry(self.main_frame, textvariable=self.actually_time, width=5).grid(row=1, column=1, padx=5, pady=5)
self.timer_label = ttk.Label(self.main_frame, text="00:00", font=("Arial", 40))
self.timer_label.grid(row=2, column=0, columnspan=2, pady=20)
self.start_stop_button = ttk.Button(self.main_frame, text="開始", command=self.toggle_timer)
self.start_stop_button.grid(row=3, column=0, columnspan=2, pady=10)
self.reset_button = ttk.Button(self.main_frame, text="リセット", command=self.reset_timer)
self.reset_button.grid(row=4, column=0, columnspan=2, pady=10)
def toggle_timer(self):
if self.is_running:
self.is_running = False
self.start_stop_button.config(text="再開")
else:
self.remaining_seconds = self.illusion_time.get() * 60
self.start_timer()
def start_timer(self):
self.is_running = True
self.start_stop_button.config(text="停止")
self.run_timer()
def initialize_timer(self):
self.time_ratio = self.actually_time.get() / self.illusion_time.get()
def run_timer(self):
if self.remaining_seconds > 0 and self.is_running:
minutes, seconds = divmod(self.remaining_seconds, 60)
self.timer_label.config(text=f"{str(minutes).zfill(2)}:{str(seconds).zfill(2)}")
self.remaining_seconds -= 1
self.root.after(int(self.time_ratio * 1000), self.run_timer)
elif self.remaining_seconds <= 0:
self.timer_label.config(text="00:00", foreground="red")
messagebox.showinfo("タイマー終了", "タイマーが終了しました!")
self.start_stop_button.config(text="開始", state="disable")
self.is_running = False
def reset_timer(self):
self.is_running = False
self.remaining_seconds = self.illusion_time.get() * 60
self.timer_label.config(text=self.format_time(self.remaining_seconds), foreground="black")
self.start_stop_button.config(text="開始", state="normal")
@staticmethod
def format_time(seconds):
minutes, seconds = divmod(seconds, 60)
return f"{str(minutes).zfill(2)}:{str(seconds).zfill(2)}"
if __name__ == "__main__":
root = tk.Tk()
app = IllusionTimerApp(root)
root.mainloop()
最後に
tkinterを使って錯覚を起こすタイマーを作成しました。設定時間によっては明らかにタイマーの進みが遅いですが意外と使えます。簡単に試すことができるのでぜひ使ってみてください。