一百多行 Python 代码手写蕃茄钟

Posted on Mon 24 October 2022 in Journal

Abstract 一百多行 Python 代码手写蕃茄钟
Authors Walter Fan
 Category    learning note  
Status v1.0
Updated 2022-10-24
License CC-BY-NC-ND 4.0

对现实不满,充满无力感,可是作为一个码农,大时代里的一个小人物,并不能改变什么,只能在程序代码里的世界里找点乐趣吧, 东坡先生如是说: 莫听穿林打叶声,何妨吟啸且徐行。竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生。 料峭春风吹酒醒,微冷,山头斜照却相迎。回首向来萧瑟处,归去,也无风雨也无晴。

TomatoTimer 是我常用了一个网站,用来践行蕃茄工作法

snapshot

可是我想修改默认的时间,加入一点提醒音乐,这个网站我也改不了,不如自己手写一个,界面如下

tomato timer

运行它很简单,只要有 python 环境就行了

git clone https://github.com/walterfan/tomato-timer.git
pip install -r requirements.txt
./tomato_timer.py

代码也是区区一百行出头

#!/usr/bin/env python3

import time
from datetime import datetime, timezone
from tkinter import Tk, StringVar, Entry, Label, Button, ttk, messagebox
from playsound import playsound

DEFAULT_MINS = 25
TIME_FORMAT = "%Y-%m-%d %H:%M:%S"

class TomatoTimer:

    def __init__(self, title = "Tomato Timer", frameSize="360x240"):
        self._root = Tk()
        self._style = ttk.Style()
        self._style.theme_use('alt')

        self._root.geometry(frameSize)
        self._root.title(title)

        self._hour=StringVar()
        self._minute=StringVar()
        self._second=StringVar()

        self.init_ui()

        self._started = False
        self._tomato_count = 0

    def set_time(self, hour=0, min=DEFAULT_MINS, sec=0):
        self._hour.set("{0:2d}".format(hour))
        self._minute.set("{0:2d}".format(min))
        self._second.set("{0:2d}".format(sec))

    def create_time_box(self, label):
        return Entry(self._root, width=4,font=("Arial",18,""), justify='center', textvariable=label)

    def init_ui(self):

        self.set_time()
        x_value = 90
        y_value = 80
        x_step = 60

        hour_box = self.create_time_box(self._hour)
        hour_box.place(x=x_value, y=y_value)

        x_value += x_step
        mins_box = self.create_time_box(self._minute)
        mins_box.place(x=x_value,y=y_value)

        x_value += x_step
        sec_box = self.create_time_box(self._second)
        sec_box.place(x=x_value,y=y_value)

        label = Label(self._root, text= "Focus on righ now",font=('Helvetica bold', 20))

        label.pack(pady=20)

        y_value += 40
        btnStart = Button(self._root, text='Start', bd='5', fg="green", command= self.countdown)
        btnStart.place(x = 80,y = y_value)

        btnStop = Button(self._root, text='Stop', bd='5', fg="blue", command= self.pause)
        btnStop.place(x = 140,y = y_value)

        btnReset = Button(self._root, text='Reset', bd='5', fg="red", command= self.reset)
        btnReset.place(x = 200,y = y_value)

    def stay_on_top(self):
        self._root.lift()
        self._root.after(2000, self.stay_on_top)

    def run(self):
        self.stay_on_top()
        self._root.mainloop()

    def reset(self):
        self._started = False
        self.set_time()

    def pause(self):
        self._started = False

    def get_hour_min_sec(self, left_seconds):

        mins,secs = divmod(left_seconds, 60)

        hours=0
        if mins > 60:
            hours, mins = divmod(mins, 60)
        return hours, mins, secs

    def countdown(self):
        self._started = True
        try:
            left_seconds = int(self._hour.get())*3600 + int(self._minute.get())*60 + int(self._second.get())
        except:
            messagebox.showwarning('', 'Invalid Input Value!')

        while self._started:

            hours, mins, secs = self.get_hour_min_sec(left_seconds)
            self.set_time(hours, mins, secs)

            self._root.update()
            time.sleep(1)

            if (left_seconds == 0):
                self._tomato_count += 1
                print("It is time: {}, count={}".format( datetime.now().strftime(TIME_FORMAT),self._tomato_count))
                playsound('starlet.wav', block = False)
                break

            left_seconds -= 1


if __name__ == '__main__':
    timer = TomatoTimer()
    timer.run()


本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。