基于Python實(shí)現(xiàn)Windows桌面定時(shí)提醒休息程序
當(dāng)我們長(zhǎng)期在電腦面前坐太久后,會(huì)產(chǎn)生一系列健康風(fēng)險(xiǎn),包括干眼癥,頸椎,腰椎,肌肉僵硬等等。解決方案是在一定的時(shí)間間隔內(nèi)我們需要have a break, 遠(yuǎn)眺可以緩解干眼癥等眼部癥狀,站起來走動(dòng)兩步,或者做一些舒展動(dòng)作,可以讓我們身體肌肉放松。Microsoft Store的一些第三方免費(fèi)定時(shí)提醒程序,如BreakTimer, 常常難以在約定的時(shí)間內(nèi)喚起。其他一些有著類似功能且有更豐富特性的第三方程序需要注冊(cè)繳費(fèi)才能使用很多功能。這觸發(fā)了我自己寫一個(gè)程序來實(shí)現(xiàn)該功能。
因?yàn)镻ython的功能強(qiáng)大,且開發(fā)程序的門檻低,所以我選擇它,我電腦安裝的版本是3.10. 第一步,開發(fā)一個(gè)可以顯示在底部工具欄右邊隱藏托盤的圖標(biāo),當(dāng)我們有鼠標(biāo)放上去時(shí),可以顯示當(dāng)前離下一次休息還剩下的時(shí)間,以分鐘和秒計(jì)。點(diǎn)擊鼠標(biāo)右鍵時(shí),可以彈出菜單顯示當(dāng)前剩余時(shí)間和退出按鈕。
要實(shí)現(xiàn)以上功能,需要安裝第三方庫(kù) pystray 和 pillow。代碼如下:
import threading from pystray import Icon, MenuItem, Menu from PIL import Image, ImageDraw def create_image(): # Load an existing image for the tray icon icon_path = r"C:\technical learning\Python\take-break-icon.png" # Path to your image file (e.g., .png or .ico) return Image.open(icon_path) def stop_program(icon, item): # Stop the video playback and exit the program global keep_run icon.stop() keep_run=False def start_tray_icon(icon): # Create the system tray icon with a menu icon.run() myicon = Icon("VideoPlayer", create_image()) # Start the tray icon in a separate thread tray_thread = threading.Thread(target=start_tray_icon, args=[myicon],daemon=True) tray_thread.start() def update_tray_menu(icon): # Update the menu with the remaining time global time_left #the tray menu has three items, time left, set timer, and stop menu = Menu( MenuItem(f"Time left: {time_left[0]} minutes {time_left[1]} seconds", lambda icon,item:None), MenuItem('Set Timer', set_timer), # Add the new menu option here MenuItem('Stop', action=stop_program) ) icon.menu = menu #the title will show when you mouse over the icon icon.title = f"{time_left}"
首先通過已有的圖片創(chuàng)建一個(gè)Icon object,并創(chuàng)建一個(gè)線程來運(yùn)行該object。因?yàn)橐獙?shí)時(shí)顯示剩余時(shí)間,所以有一個(gè)update函數(shù)來對(duì)Menu內(nèi)容進(jìn)行更新。
第二步,實(shí)現(xiàn)每隔預(yù)設(shè)的時(shí)間, 啟動(dòng)VLC播放器,播放一段指定的視頻。同時(shí)計(jì)時(shí)器重新開始倒計(jì)時(shí)。
import subprocess import time # Path to VLC and your video file vlc_path = r"D:\Program Files (x86)\VideoLAN\VLC\vlc.exe" # Update if needed video_path = r"C:\technical learning\Python\Health_song_Fxx.mp4" #the minutes and seconds to pass to have a break periodically,default is 60 minutes time_set = (59,60) # Global variable to track time left time_left = list(time_set) keep_run = True def start_play_video(): subprocess.run([vlc_path, video_path]) while keep_run: update_tray_menu(myicon) #you can see the update of time_left instantly if time_left[0]==-1: #it's the time for a break video_play_thread = threading.Thread(target=start_play_video) video_play_thread.start() time_left = list(time_set) # Reset time left time.sleep(1) if time_left[1]==0: time_left[1]=60 time_left[0]-=1 time_left[1] -= 1
主線程是一個(gè)while loop,每隔1s更新time_left,當(dāng)time out,啟動(dòng)一個(gè)線程來通過subprocess來調(diào)用VLC播放器來播放視頻,之所以用subprocess是這樣一般可以帶來前臺(tái)窗體播放的效果,更好的提醒作用。當(dāng)Icon點(diǎn)擊了stop后,keep_run為False,循環(huán)退出,程序結(jié)束。
最簡(jiǎn)單功能的桌面定時(shí)提醒程序這時(shí)候可以告一段落了,但是在你使用電腦的過程中,你可能本身會(huì)中途離開,比方說中午午餐,去開會(huì),或者去做運(yùn)動(dòng)了。這時(shí)候電腦進(jìn)入休眠狀態(tài)。當(dāng)你回來后,計(jì)時(shí)器還是會(huì)按照計(jì)算機(jī)休眠前剩余的時(shí)間繼續(xù)計(jì)時(shí),這個(gè)不太合理。因?yàn)檫@個(gè)時(shí)候你其實(shí)已經(jīng)眼睛和身體已經(jīng)得到了一些放松,起碼沒有一直盯著屏幕。所以應(yīng)該重新開始計(jì)時(shí)。
要實(shí)現(xiàn)Windows計(jì)算機(jī)從休眠中醒來重新計(jì)數(shù),需要安裝第三方庫(kù)pywin32,別被名字糊弄,因?yàn)闅v史原因,它后續(xù)的版本也包括了64 bit windows.
import win32api import win32gui import win32con #the class used to handle event of computer waking up from hibernation class PowerEventHandler: def __init__(self): self.internal_variable = 0 def handle_event(self, hwnd, msg, wparam, lparam): global time_left if msg == win32con.WM_POWERBROADCAST and wparam == win32con.PBT_APMRESUMEAUTOMATIC: #print("Laptop woke up from hibernation!") time_left = [59,60] list(time_set) return True '''creates a custom Windows Message Handling Window''' handler = PowerEventHandler() wc = win32gui.WNDCLASS() wc.lpszClassName = 'PowerHandler' wc.hInstance = win32api.GetModuleHandle(None) wc.lpfnWndProc = handler.handle_event class_atom = win32gui.RegisterClass(wc) #create a window of the registered class with no size and invisible hwnd = win32gui.CreateWindow(class_atom, 'PowerHandler', 0, 0, 0, 0, 0, 0, 0, wc.hInstance, None)
創(chuàng)建一個(gè)不可見窗體來接受Windows系統(tǒng)的消息,當(dāng)接收到從休眠中醒來的消息時(shí),重置剩下的時(shí)間為預(yù)設(shè)值。同時(shí)你需要在while loop里不斷地處理pending的Windows系統(tǒng)消息。
win32gui.PumpWaitingMessages()
第四步,目前為止,隔多少時(shí)間休息的時(shí)間段是在程序里寫死的,默認(rèn)是60分鐘。用戶可能需要根據(jù)自己的偏好進(jìn)行修改。那么需要在Icon的Menu里增加一個(gè)選項(xiàng),點(diǎn)擊后彈框進(jìn)行時(shí)間段設(shè)置。
這里就要用到tkinter lib,這個(gè)默認(rèn)在Pythond的安裝包里,無需另外安裝。
import tkinter as tk from tkinter import simpledialog #a pop up dialog to set the time_set def set_timer(icon, item): #after the user clicking the set button def validate_and_set_time(): nonlocal root, error_label try: minutes = int(minute_input.get()) seconds = int(second_input.get()) #print(minutes,seconds) # Validate range [0, 60] if 0 <= minutes <= 60 and 0 <= seconds <= 60: with time_left_lock: global time_set,time_left time_set=(minutes,seconds) time_left=list(time_set) #each time_set is set, time_let needs to update accordingly #print(time_left) root.destroy() # Close dialog if input is valid else: error_label.config(text="Minutes and seconds must be between 0 and 60!") except ValueError: error_label.config(text="Please enter valid integers!") #create the dialog root = tk.Tk() root.title("Set Timer") root.geometry("300x200") # Get screen width and height screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() # Calculate position x and y to center the window window_width = 300 window_height = 200 position_x = (screen_width // 2) - (window_width // 2) position_y = (screen_height // 2) - (window_height // 2) # Set the geometry to center the window root.geometry(f"{window_width}x{window_height}+{position_x}+{position_y}") tk.Label(root, text="Set Timer").pack(pady=5) tk.Label(root, text="Minutes (0-60):").pack() minute_input = tk.Entry(root) minute_input.pack() tk.Label(root, text="Seconds (0-60):").pack() second_input = tk.Entry(root) second_input.pack() error_label = tk.Label(root, text="", fg="red") # Label for error messages error_label.pack(pady=5) #set the button call-back method to validate_and_set_time tk.Button(root, text="Set", command=validate_and_set_time).pack(pady=10) root.mainloop()
上面的代碼就包括了彈窗設(shè)計(jì),用戶輸入數(shù)據(jù)校驗(yàn),間隔時(shí)間段設(shè)置,以及剩余時(shí)間重置等。
另外,在Icon的Menu里需增加一欄,用于設(shè)置間隔時(shí)間段。
MenuItem('Set Timer', set_timer), # Add the new menu option here
最后一步,為了讓用戶設(shè)置的時(shí)間段間隔永久生效,需要用一個(gè)文件來存儲(chǔ)。 啟動(dòng)這個(gè)程序的時(shí)候,從這個(gè)文件讀數(shù)據(jù),退出程序的時(shí)候,把數(shù)據(jù)存入到該文件。
這是鼠標(biāo)移到Icon上,點(diǎn)擊右鍵出現(xiàn)的Menu:
下面是點(diǎn)擊Set Timer后的彈框。
到此這篇關(guān)于基于Python實(shí)現(xiàn)Windows桌面定時(shí)提醒休息程序的文章就介紹到這了,更多相關(guān)Python定時(shí)提醒內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python 協(xié)程中的迭代器,生成器原理及應(yīng)用實(shí)例詳解
這篇文章主要介紹了python 協(xié)程中的迭代器,生成器原理及應(yīng)用,結(jié)合具體實(shí)例形式詳細(xì)分析了Python協(xié)程中的迭代器,生成器概念、原理及應(yīng)用操作技巧,需要的朋友可以參考下2019-10-10django+tornado實(shí)現(xiàn)實(shí)時(shí)查看遠(yuǎn)程日志的方法
今天小編就為大家分享一篇django+tornado實(shí)現(xiàn)實(shí)時(shí)查看遠(yuǎn)程日志的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-08-08Python實(shí)現(xiàn)刪除某列中含有空值的行的示例代碼
這篇文章主要介紹了Python實(shí)現(xiàn)刪除某列中含有空值的行的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Python3利用Dlib19.7實(shí)現(xiàn)攝像頭人臉識(shí)別的方法
這篇文章主要介紹了Python 3 利用 Dlib 19.7 實(shí)現(xiàn)攝像頭人臉識(shí)別 ,利用python開發(fā),借助Dlib庫(kù)捕獲攝像頭中的人臉,提取人臉特征,通過計(jì)算歐氏距離來和預(yù)存的人臉特征進(jìn)行對(duì)比,達(dá)到人臉識(shí)別的目的,感興趣的小伙伴們可以參考一下2018-05-05python網(wǎng)絡(luò)爬蟲實(shí)現(xiàn)個(gè)性化音樂播放器示例解析
這篇文章主要為大家介紹了使用python網(wǎng)絡(luò)爬蟲實(shí)現(xiàn)個(gè)性化音樂播放器的詳細(xì)示例代碼以及內(nèi)容解析,有需要的朋友?可以借鑒參考下希望能夠有所幫助2022-03-03Python中使用matplotlib繪制mqtt數(shù)據(jù)實(shí)時(shí)圖像功能
這篇文章主要介紹了Python中使用matplotlib繪制mqtt數(shù)據(jù)實(shí)時(shí)圖像,本代碼中publish是一個(gè)死循環(huán),數(shù)據(jù)一直往外發(fā)送,詳細(xì)代碼跟隨小編一起通過本文學(xué)習(xí)下吧2021-09-09基于Python+Flask實(shí)現(xiàn)一個(gè)簡(jiǎn)易網(wǎng)頁驗(yàn)證碼登錄系統(tǒng)案例
當(dāng)今的互聯(lián)網(wǎng)世界中,為了防止惡意訪問,許多網(wǎng)站在登錄和注冊(cè)表單中都采用了驗(yàn)證碼技術(shù),驗(yàn)證碼可以防止機(jī)器人自動(dòng)提交表單,確保提交行為背后有一個(gè)真實(shí)的人類用戶,本文將向您展示如何使用Python的Flask框架來創(chuàng)建一個(gè)簡(jiǎn)單的驗(yàn)證碼登錄系統(tǒng)2023-09-09Django中使用SMTP實(shí)現(xiàn)郵件發(fā)送功能
在?Django?中使用?SMTP?發(fā)送郵件是一個(gè)常見的需求,通常用于發(fā)送用戶注冊(cè)確認(rèn)郵件、密碼重置郵件等,下面我們來看看如何在?Django?中配置?SMTP?發(fā)送郵件吧2025-01-01