首頁 > 軟體

基於Python寫一個番茄鍾小工具

2022-12-03 14:01:03

一、功能簡述

番茄鍾即番茄工作法,番茄工作法是簡單易行的時間管理工具,使用番茄工作法即一個番茄時間共30分鐘,25分鐘工作,5分鐘休息;

特點一:番茄時長有三檔

因為這個工具本人也是考慮到每個人情況不一樣,不一定25分鐘就適合自己,所以將番茄鍾時長設為30min/45min/60min三檔,自由選擇

特點二:番茄統計功能

特點三:休息期間會自動播放放鬆音樂,當然不喜歡也支援禁止播放放鬆音樂,休息時間結束後,音樂也會自動停止(意味著又要開始“搬磚”了)

特點四:番茄鍾結束後,會有蜂鳴音提示,並且跳出彈框

二、使用到的主要模組

tkinter:用於介面設計

winsound:用於呼叫蜂鳴器提示音

pygame:用於音樂播放

time:時間相關的格式轉換

三、核心模組程式碼分析

程式碼的主要思路是主函數中,利用tkinter模組佈局介面、按鈕、標籤等元件,然後將番茄鍾、休息兩大核心功能封裝到函數中,一旦點選對應的按鈕,即開啟一個新執行緒用於執行對應的功能,同時通過全域性變數thread_flag來保持永遠只有主執行緒和功能執行緒2個執行緒,避免多次點選,產生多個執行緒同時執行,造成番茄鍾混亂;

1、番茄鐘模組

## 建立番茄計時函數
def tomato_clock(remain_time):    
    # 如果在休息時間未結束就開啟番茄鍾,則停止音樂
    pygame.mixer.music.pause()
    
    # 用來提醒使用者選擇番茄鍾時長,為選擇的話,就跳出函數,結束執行緒
    if remain_time == 0:
        lb3.configure(text='請先選擇番茄鍾時長')
        return
    print(remain_time)
    
    # gmtime這裡是將時間轉化為計算機可處理的時間格式即time_t到tm型別的轉換;不是重點,知道是格式轉化即可
    # strptime()函數將字串轉換為datetime
    begin_time = time.strftime('%M:%S', time.gmtime(remain_time))
    
    # 將時間內容列印到介面上
    lb2.configure(text=begin_time)
    lb3.configure(text='總時間/剩餘時間')
    
    # 用於保證番茄鍾執行緒或者休息執行緒只有一個能存在,這個也是本人覺得比較巧的一個點
    global thread_flag
    if thread_flag:
        thread_flag = False
    else:
        thread_flag = True
    tmp_thread_flag = thread_flag
    
    # 時間變化部分
    for i in range(remain_time):
        # 如果收到休息執行緒導致的thread_flag標誌位的變化,則退出執行緒
        if tmp_thread_flag != thread_flag:
            return
        
        remain_time -= 1
        remain_time_str = time.strftime('/ %M:%S', time.gmtime(remain_time))
        
        # 將時鐘實時更新到介面上
        lb1.configure(text=remain_time_str)
        root.update()
        time.sleep(1)
        
        #時間到了,開啟蜂鳴提醒與提示框提醒
        if remain_time == 0:
            Beep(500, 800)
            tomato_count()
            mymsg()
    lb1.configure(text=begin_time)
    
    #使用者確認後,自動進入休息模式
    relax()

2、音樂控制函數

# 音樂控制函數,用來控制是否允許休息時播放音樂,其實本質只是靜音而已,狗頭.jpg
# 在定義時,music_flag已經初始化True,代表執行休息時播放音樂
def music_allow():
    global music_flag        #宣告全域性變數
    # 如果已經是True(即不禁止音樂時),勾選了按鈕,則music_flag 變為 False,禁止音樂
    if music_flag:
        music_flag = False
        pygame.mixer.music.set_volume(0.0)
    else:
        # 代表取消勾選,不禁止音樂
        music_flag = True
        pygame.mixer.music.set_volume(0.5)

3、main中的按鈕部分

# 每當按鈕點選後,就會產生一個執行緒,執行對應的功能,和主執行緒並行
# 以防止單執行緒的話,進入番茄鍾或者休息時,介面中的其他功能按鈕失效

# 開啟番茄鍾按鈕,使用lambda構造匿名函數是因為command後接的函數如果有引數會失效,這點本人也不清楚,沒去深究,直接匿名函數走去
# 同時daemon=True,即將執行緒設為守護執行緒,解決主執行緒退出時,其他執行緒不正常退出的問題
Button1 = tk.Button(root, text='開啟一個番茄', bg='orange', fg='black', font='Verdana 13 bold',width=15,
    height=1, command=lambda: threading.Thread(target=tomato_clock, daemon=True,args=(var.get(),)).start())
Button1.place(x=70, y=150)

# 休息一下按鈕
Button2 = tk.Button(root, text='休息一下', bg='cornflowerblue', fg='black', font='Verdana 13 bold',
                        width=15,height=1,command=lambda:threading.Thread(target=relax,daemon=True).start())
Button2.place(x=70, y=200)

四、整體程式碼

# -*- coding:utf-8 -*-
import tkinter as tk
import tkinter.messagebox
from winsound import Beep
import threading
import sys
import pygame
import time

# 用於統計完成的番茄鍾個數
count = 0
# 執行緒切換標誌
thread_flag = True
# 音樂開關標誌
music_flag = True

# 呼叫Tk()建立主視窗
root = tk.Tk()
# 給主視窗起一個名字,也就是視窗的名字
root.title('Rio的番茄鍾')
# 設定視窗大小:寬x高,注,此處不能為 "*",必須使用 "x"
root.geometry('460x300')
root.configure(bg='Tomato')


# 建立完成計時後的彈窗
def mymsg():
    try:
        tk.messagebox.showinfo("提示", "恭喜完成一個番茄鍾!!記得休息一下")
    except Exception as e:
        print(type(e), e)
        sys.exit()

# 休息結束彈窗
def mymsg2():
    tk.messagebox.showinfo("提示", "休息完畢!")

# 建立番茄計時函數
# strptime()函數將字串轉換為datetime
def tomato_clock(remain_time):
    # 如果在休息時間未結束就開啟番茄鍾,則停止音樂
    pygame.mixer.music.pause()
    # 避免未進行番茄鍾時長選擇
    if remain_time == 0:
        lb3.configure(text='請先選擇番茄鍾時長')
        return
    print(remain_time)
    begin_time = time.strftime('%M:%S', time.gmtime(remain_time))
    lb2.configure(text=begin_time)
    lb3.configure(text='總時間/剩餘時間')
    global thread_flag
    if thread_flag:
        thread_flag = False
    else:
        thread_flag = True
    tmp_thread_flag = thread_flag
    for i in range(remain_time):
        if tmp_thread_flag != thread_flag:
            return
        remain_time -= 1
        remain_time_str = time.strftime('/ %M:%S', time.gmtime(remain_time))
        lb1.configure(text=remain_time_str)
        root.update()
        time.sleep(1)
        if remain_time == 0:
            Beep(500, 800)
            tomato_count()
            mymsg()
    lb1.configure(text=begin_time)
    relax()


# 建立番茄計數的函數
def tomato_count():
    global count
    count += 1
    lb4.configure(text=count)

# 建立休息時間函數
def relax():
    remain_time = 480   # 休息8分鐘
    begin_time = time.strftime('%M:%S', time.gmtime(remain_time))
    lb2.configure(text=begin_time)
    lb3.configure(text='總時間/剩餘時間')

    # 執行緒標誌,用於結束舊執行緒
    global thread_flag
    if thread_flag:
        thread_flag = False
    else:
        thread_flag = True
    tmp_thread_flag = thread_flag
    pygame.mixer.music.play(-1)
    for i in range(remain_time):
        if tmp_thread_flag != thread_flag:
            return
        remain_time -= 1
        remain_time_str = time.strftime('/ %M:%S', time.gmtime(remain_time))
        lb1.configure(text=remain_time_str)
        root.update()
        time.sleep(1)
        if remain_time == 0:
            pygame.mixer.music.pause()
            mymsg2()
    lb1.configure(text=begin_time)

# 音樂控制函數
def music_allow():
    global music_flag
    # 如果已經是True(即不禁止音樂時),勾選了按鈕,則music_flag 變為 False,禁止音樂
    if music_flag:
        music_flag = False
        pygame.mixer.music.set_volume(0.0)
    else:
        music_flag = True
        pygame.mixer.music.set_volume(0.5)

if __name__ == "__main__":

    #音樂初始化
    pygame.mixer.init()
    # 異常丟擲,防止沒有放音樂檔案
    try:
        pygame.mixer.music.load('music.mp3')
    except Exception as e:
        print(type(e), e)
        tk.messagebox.showinfo("提示", "無檔案music.mp3或改檔案路徑不對")
        sys.exit()
    pygame.mixer.music.set_volume(0.5)
    # 建立變數
    var = tk.IntVar()
    # 給變數賦初值為30
    var.set(30)

    # 番茄動態計時
    lb1 = tk.Label(root, text='0', bg='Tomato', fg='white', font='Verdana 16 bold', width=7, height=1)
    lb1.place(x=130, y=100)

    # 番茄固定時間
    lb2 = tk.Label(root, text='0', bg='Tomato', fg='white', font='Verdana 16 bold', width=5, height=1)
    lb2.place(x=60, y=100)

    # 剩餘時間/總時間
    lb3 = tk.Label(root, text=' ', bg='Tomato', fg='white', font='Verdana 16 bold', width=14, height=2)
    lb3.place(x=50, y=44)

    # 番茄個數顯示
    lb4 = tk.Label(root, text='0', bg='Tomato', fg='white', font='Verdana 16 bold', width=7, height=1)
    lb4.place(x=90, y=20)

    # 左上角的 番茄:
    lb5 = tk.Label(root, text='已積累番茄:', bg='Tomato', fg='white', font='Verdana 16 bold', width=8, height=1)
    lb5.place(x=5, y=20)

    # 按鈕
    ##創造一個frame來收納按鈕
    fr1 = tk.LabelFrame(root,bg='LightGreen',text='選擇番茄鍾時長', relief='groove', bd=1,)
    fr1.pack(side='right')
    r1 = tk.Radiobutton(fr1, text='30min', variable=var, bg='LightGreen', value=1800)
    r1.pack()
    r2 = tk.Radiobutton(fr1, text='45min', variable=var, bg='LightGreen', value=2700)
    r2.pack()
    r3 = tk.Radiobutton(fr1, text='60min', variable=var, bg='LightGreen', value=3599)
    r3.pack()
    Checkbutton = tk.Checkbutton(fr1, text="是否禁止音樂", fg='black', bg='LightGreen', command=music_allow)
    Checkbutton.pack()

    # 開啟一個番茄
    #利用多執行緒,避免進入番茄鍾後,退出按鈕失效
    Button1 = tk.Button(root, text='開啟一個番茄', bg='orange', fg='black', font='Verdana 13 bold',width=15,
                      height=1, command=lambda: threading.Thread(target=tomato_clock, daemon=True,args=(var.get(),)).start())
    Button1.place(x=70, y=150)

    # 休息一下
    Button2 = tk.Button(root, text='休息一下', bg='cornflowerblue', fg='black', font='Verdana 13 bold',
                        width=15, height=1, command=lambda: threading.Thread(target=relax, daemon=True).start())
    Button2.place(x=70, y=200)

    # 新增按鈕,以及按鈕的文字,並通過command 引數設定關閉視窗的功能
    button = tk.Button(root, text="退出", fg='black', bg='YellowGreen', width=15, command=root.quit)
    # 將按鈕放置在主視窗內
    button.place(x=105, y=250)

    #開啟主迴圈,讓視窗處於顯示狀態
    root.mainloop()

到此這篇關於基於Python寫一個番茄鍾小工具的文章就介紹到這了,更多相關Python番茄鍾內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com