網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
一、功能簡(jiǎn)述
番茄鐘即番茄工作法,番茄工作法是簡(jiǎn)單易行的時(shí)間管理工具,使用番茄工作法即一個(gè)番茄時(shí)間共30分鐘,25分鐘工作,5分鐘休息;
特點(diǎn)一:番茄時(shí)長(zhǎng)有三檔
因?yàn)檫@個(gè)工具本人也是考慮到每個(gè)人情況不一樣,不一定25分鐘就適合自己,所以將番茄鐘時(shí)長(zhǎng)設(shè)為30min/45min/60min三檔,自由選擇
特點(diǎn)二:番茄統(tǒng)計(jì)功能
特點(diǎn)三:休息期間會(huì)自動(dòng)播放放松音樂(lè),當(dāng)然不喜歡也支持禁止播放放松音樂(lè),休息時(shí)間結(jié)束后,音樂(lè)也會(huì)自動(dòng)停止(意味著又要開(kāi)始“搬磚”了)
特點(diǎn)四:番茄鐘結(jié)束后,會(huì)有蜂鳴音提示,并且跳出彈框
二、使用到的主要模塊
tkinter:用于界面設(shè)計(jì)
winsound:用于調(diào)用蜂鳴器提示音
pygame:用于音樂(lè)播放
time:時(shí)間相關(guān)的格式轉(zhuǎn)換
三、核心模塊代碼分析
代碼的主要思路是主函數(shù)中,利用tkinter模塊布局界面、按鈕、標(biāo)簽等組件,然后將番茄鐘、休息兩大核心功能封裝到函數(shù)中,一旦點(diǎn)擊對(duì)應(yīng)的按鈕,即開(kāi)啟一個(gè)新線程用于執(zhí)行對(duì)應(yīng)的功能,同時(shí)通過(guò)全局變量thread_flag來(lái)保持永遠(yuǎn)只有主線程和功能線程2個(gè)線程,避免多次點(diǎn)擊,產(chǎn)生多個(gè)線程同時(shí)運(yùn)行,造成番茄鐘混亂;
1、番茄鐘模塊
## 創(chuàng)建番茄計(jì)時(shí)函數(shù)
def tomato_clock(remain_time):
# 如果在休息時(shí)間未結(jié)束就開(kāi)啟番茄鐘,則停止音樂(lè)
pygame.mixer.music.pause()
# 用來(lái)提醒用戶選擇番茄鐘時(shí)長(zhǎng),為選擇的話,就跳出函數(shù),結(jié)束線程
if remain_time == 0:
lb3.configure(text='請(qǐng)先選擇番茄鐘時(shí)長(zhǎng)')
return
print(remain_time)
# gmtime這里是將時(shí)間轉(zhuǎn)化為計(jì)算機(jī)可處理的時(shí)間格式即time_t到tm類型的轉(zhuǎn)換;不是重點(diǎn),知道是格式轉(zhuǎn)化即可
# strptime()函數(shù)將字符串轉(zhuǎn)換為datetime
begin_time = time.strftime('%M:%S', time.gmtime(remain_time))
# 將時(shí)間內(nèi)容打印到界面上
lb2.configure(text=begin_time)
lb3.configure(text='總時(shí)間/剩余時(shí)間')
# 用于保證番茄鐘線程或者休息線程只有一個(gè)能存在,這個(gè)也是本人覺(jué)得比較巧的一個(gè)點(diǎn)
global thread_flag
if thread_flag:
thread_flag = False
else:
thread_flag = True
tmp_thread_flag = thread_flag
# 時(shí)間變化部分
for i in range(remain_time):
# 如果收到休息線程導(dǎo)致的thread_flag標(biāo)志位的變化,則退出線程
if tmp_thread_flag != thread_flag:
return
remain_time -= 1
remain_time_str = time.strftime('/ %M:%S', time.gmtime(remain_time))
# 將時(shí)鐘實(shí)時(shí)更新到界面上
lb1.configure(text=remain_time_str)
root.update()
time.sleep(1)
#時(shí)間到了,開(kāi)啟蜂鳴提醒與提示框提醒
if remain_time == 0:
Beep(500, 800)
tomato_count()
mymsg()
lb1.configure(text=begin_time)
#使用者確認(rèn)后,自動(dòng)進(jìn)入休息模式
relax()
2、音樂(lè)控制函數(shù)
# 音樂(lè)控制函數(shù),用來(lái)控制是否允許休息時(shí)播放音樂(lè),其實(shí)本質(zhì)只是靜音而已,狗頭.jpg
# 在定義時(shí),music_flag已經(jīng)初始化True,代表運(yùn)行休息時(shí)播放音樂(lè)
def music_allow():
global music_flag #聲明全局變量
# 如果已經(jīng)是True(即不禁止音樂(lè)時(shí)),勾選了按鈕,則music_flag 變?yōu)?False,禁止音樂(lè)
if music_flag:
music_flag = False
pygame.mixer.music.set_volume(0.0)
else:
# 代表取消勾選,不禁止音樂(lè)
music_flag = True
pygame.mixer.music.set_volume(0.5)
3、main中的按鈕部分
# 每當(dāng)按鈕點(diǎn)擊后,就會(huì)產(chǎn)生一個(gè)線程,執(zhí)行對(duì)應(yīng)的功能,和主線程并行
# 以防止單線程的話,進(jìn)入番茄鐘或者休息時(shí),界面中的其他功能按鈕失效
# 開(kāi)啟番茄鐘按鈕,使用lambda構(gòu)造匿名函數(shù)是因?yàn)閏ommand后接的函數(shù)如果有參數(shù)會(huì)失效,這點(diǎn)本人也不清楚,沒(méi)去深究,直接匿名函數(shù)走去
# 同時(shí)daemon=True,即將線程設(shè)為守護(hù)線程,解決主線程退出時(shí),其他線程不正常退出的問(wèn)題
Button1 = tk.Button(root, text='開(kāi)啟一個(gè)番茄', 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
# 用于統(tǒng)計(jì)完成的番茄鐘個(gè)數(shù)
count = 0
# 線程切換標(biāo)志
thread_flag = True
# 音樂(lè)開(kāi)關(guān)標(biāo)志
music_flag = True
# 調(diào)用Tk()創(chuàng)建主窗口
root = tk.Tk()
# 給主窗口起一個(gè)名字,也就是窗口的名字
root.title('Rio的番茄鐘')
# 設(shè)置窗口大小:寬x高,注,此處不能為 "*",必須使用 "x"
root.geometry('460x300')
root.configure(bg='Tomato')
# 創(chuàng)建完成計(jì)時(shí)后的彈窗
def mymsg():
try:
tk.messagebox.showinfo("提示", "恭喜完成一個(gè)番茄鐘!!記得休息一下")
except Exception as e:
print(type(e), e)
sys.exit()
# 休息結(jié)束彈窗
def mymsg2():
tk.messagebox.showinfo("提示", "休息完畢!")
# 創(chuàng)建番茄計(jì)時(shí)函數(shù)
# strptime()函數(shù)將字符串轉(zhuǎn)換為datetime
def tomato_clock(remain_time):
# 如果在休息時(shí)間未結(jié)束就開(kāi)啟番茄鐘,則停止音樂(lè)
pygame.mixer.music.pause()
# 避免未進(jìn)行番茄鐘時(shí)長(zhǎng)選擇
if remain_time == 0:
lb3.configure(text='請(qǐng)先選擇番茄鐘時(shí)長(zhǎng)')
return
print(remain_time)
begin_time = time.strftime('%M:%S', time.gmtime(remain_time))
lb2.configure(text=begin_time)
lb3.configure(text='總時(shí)間/剩余時(shí)間')
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()
# 創(chuàng)建番茄計(jì)數(shù)的函數(shù)
def tomato_count():
global count
count += 1
lb4.configure(text=count)
# 創(chuàng)建休息時(shí)間函數(shù)
def relax():
remain_time = 480 # 休息8分鐘
begin_time = time.strftime('%M:%S', time.gmtime(remain_time))
lb2.configure(text=begin_time)
lb3.configure(text='總時(shí)間/剩余時(shí)間')
# 線程標(biāo)志,用于結(jié)束舊線程
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)
# 音樂(lè)控制函數(shù)
def music_allow():
global music_flag
# 如果已經(jīng)是True(即不禁止音樂(lè)時(shí)),勾選了按鈕,則music_flag 變?yōu)?False,禁止音樂(lè)
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__":
#音樂(lè)初始化
pygame.mixer.init()
# 異常拋出,防止沒(méi)有放音樂(lè)文件
try:
pygame.mixer.music.load('music.mp3')
except Exception as e:
print(type(e), e)
tk.messagebox.showinfo("提示", "無(wú)文件music.mp3或改文件路徑不對(duì)")
sys.exit()
pygame.mixer.music.set_volume(0.5)
# 創(chuàng)建變量
var = tk.IntVar()
# 給變量賦初值為30
var.set(30)
# 番茄動(dòng)態(tài)計(jì)時(shí)
lb1 = tk.Label(root, text='0', bg='Tomato', fg='white', font='Verdana 16 bold', width=7, height=1)
lb1.place(x=130, y=100)
# 番茄固定時(shí)間
lb2 = tk.Label(root, text='0', bg='Tomato', fg='white', font='Verdana 16 bold', width=5, height=1)
lb2.place(x=60, y=100)
# 剩余時(shí)間/總時(shí)間
lb3 = tk.Label(root, text=' ', bg='Tomato', fg='white', font='Verdana 16 bold', width=14, height=2)
lb3.place(x=50, y=44)
# 番茄個(gè)數(shù)顯示
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)
# 按鈕
##創(chuàng)造一個(gè)frame來(lái)收納按鈕
fr1 = tk.LabelFrame(root,bg='LightGreen',text='選擇番茄鐘時(shí)長(zhǎng)', 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="是否禁止音樂(lè)", fg='black', bg='LightGreen', command=music_allow)
Checkbutton.pack()
# 開(kāi)啟一個(gè)番茄
#利用多線程,避免進(jìn)入番茄鐘后,退出按鈕失效
Button1 = tk.Button(root, text='開(kāi)啟一個(gè)番茄', 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)
# 添加按鈕,以及按鈕的文本,并通過(guò)command 參數(shù)設(shè)置關(guān)閉窗口的功能
button = tk.Button(root, text="退出", fg='black', bg='YellowGreen', width=15, command=root.quit)
# 將按鈕放置在主窗口內(nèi)
button.place(x=105, y=250)
#開(kāi)啟主循環(huán),讓窗口處于顯示狀態(tài)
root.mainloop()
原文鏈接:https://blog.csdn.net/weixin_44517500/article/details/128129974
相關(guān)推薦
- 2021-12-15 Redis可視化工具Redis?Desktop?Manager的具體使用_Redis
- 2024-01-27 DO、DTO、BO、VO、POJO區(qū)別
- 2022-10-11 MATLAB中subplot函數(shù)的語(yǔ)法與使用實(shí)例_C 語(yǔ)言
- 2022-04-16 C#算法之實(shí)現(xiàn)阿姆斯特朗數(shù)_C#教程
- 2022-02-18 解決上傳apk文件后為vnd.android.package-archive格式的問(wèn)題
- 2022-07-02 element下拉框獲取選中的內(nèi)容
- 2023-05-06 docker?search命令的具體使用_docker
- 2022-11-10 android時(shí)間選擇控件之TimePickerView使用方法詳解_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支