基于Python打造一個(gè)你的專屬中醫(yī)養(yǎng)生桌面時(shí)鐘
今天想和大家分享一個(gè)有趣又有用的小項(xiàng)目——如何使用 Python 編寫一個(gè)集成了公歷、農(nóng)歷和中醫(yī)十二時(shí)辰養(yǎng)生提示的桌面時(shí)鐘。這個(gè)項(xiàng)目不僅實(shí)用,還能讓我們在快節(jié)奏的生活中,偶爾抬頭看看屏幕,就能得到一份來自古老智慧的關(guān)懷。
效果展示

項(xiàng)目背景與靈感
隨著生活節(jié)奏的加快,越來越多的人開始關(guān)注健康和養(yǎng)生。中醫(yī)的“十二時(shí)辰養(yǎng)生法”是古人根據(jù)人體經(jīng)絡(luò)氣血運(yùn)行規(guī)律總結(jié)出的經(jīng)驗(yàn),比如“卯時(shí)(5-7點(diǎn))大腸經(jīng)當(dāng)令,適合起床喝水促進(jìn)排毒”。將這些知識融入到一個(gè)實(shí)時(shí)更新的時(shí)鐘中,既能滿足我們查看時(shí)間的基本需求,又能隨時(shí)提醒我們順應(yīng)自然規(guī)律調(diào)養(yǎng)身體,豈不是很棒?
技術(shù)實(shí)現(xiàn)詳解
我們的“中醫(yī)養(yǎng)生時(shí)鐘”主要依賴以下幾個(gè) Python 庫:
tkinter: Python 自帶的 GUI 庫,用于構(gòu)建圖形用戶界面。datetime: Python 標(biāo)準(zhǔn)庫,用于獲取和格式化當(dāng)前時(shí)間。lunardate: 一個(gè)第三方庫,專門用來處理農(nóng)歷日期轉(zhuǎn)換。需要先通過pip install lunardate安裝。
1. 核心類ChineseClock
整個(gè)程序圍繞 ChineseClock 類展開。它的 __init__ 方法負(fù)責(zé)初始化所有數(shù)據(jù)和 UI 組件。
數(shù)據(jù)準(zhǔn)備
shichen_dict: 這是一個(gè)核心字典,存儲(chǔ)了十二時(shí)辰、對應(yīng)的時(shí)間范圍(24小時(shí)制)以及對應(yīng)的養(yǎng)生提示。鍵是一個(gè)元組(時(shí)辰名, 時(shí)間范圍),值是提示字符串。lunar_months: 一個(gè)列表,將數(shù)字月份映射為農(nóng)歷月份名稱(如["正月", "二月", ...]),方便后續(xù)顯示。
用戶界面 (create_widgets)
我們創(chuàng)建了一個(gè)無邊框 (overrideredirect) 并始終置頂 (attributes('-topmost', True)) 的窗口,使其像一個(gè)小工具一樣常駐屏幕。
布局: 使用 tk.Frame 作為主容器 (main_frame),內(nèi)部元素垂直堆疊 (pack)。
組件:
gregorian_label: 顯示完整的公歷年月日時(shí)分秒。weekday_label: 顯示星期幾。lunar_label: 顯示農(nóng)歷日期。shichen_label: 顯示當(dāng)前時(shí)辰及其養(yǎng)生提示。close_button: 一個(gè)簡潔的“×”號按鈕,放在窗口右上角,用于關(guān)閉程序。- 樣式: 設(shè)置了不同的字體大小、顏色和背景色,使其看起來更美觀、信息層次分明。例如,公歷時(shí)間用綠色,星期用黃色,農(nóng)歷用金色,時(shí)辰提示用紅色。
功能函數(shù)
get_lunar_date(): 調(diào)用LunarDate.fromSolarDate獲取今天的農(nóng)歷日期對象。然后處理月份(包括閏月)和日期(通過number_to_chinese函數(shù)將數(shù)字轉(zhuǎn)換為“初一”、“初二”等)的格式化,最終返回如“農(nóng)歷:二零二六年正月初一”的字符串。get_shichen(): 獲取當(dāng)前小時(shí) (datetime.now().hour),遍歷shichen_dict,判斷當(dāng)前小時(shí)落在哪個(gè)時(shí)辰范圍內(nèi)。特別注意處理跨天的“子時(shí)”(23:00-01:00)。找到后返回格式化的提示信息,如“子時(shí)(23:00-01:00)· 膽經(jīng)運(yùn)行,及時(shí)入睡養(yǎng)陽氣”。update_time(): 這是驅(qū)動(dòng)時(shí)鐘的核心函數(shù)。它:- 獲取當(dāng)前時(shí)間 (
now)。 - 更新公歷、星期、農(nóng)歷標(biāo)簽的文本。
- 調(diào)用
get_shichen更新時(shí)辰提示。 - 使用
self.root.after(1000, self.update_time)遞歸調(diào)用自身,實(shí)現(xiàn)每秒刷新一次顯示。
- 獲取當(dāng)前時(shí)間 (
可拖動(dòng)窗口 (bind_drag_events,start_drag,on_drag)
為了讓時(shí)鐘可以隨意移動(dòng)到屏幕的任意位置,我們實(shí)現(xiàn)了窗口拖動(dòng)功能。
- 我們?yōu)?
main_frame內(nèi)的所有子組件(除了close_button)以及root窗口本身綁定了鼠標(biāo)事件<ButtonPress-1>和<B1-Motion>。 start_drag: 記錄鼠標(biāo)按下的初始坐標(biāo)(相對于被點(diǎn)擊組件的位置)。on_drag: 當(dāng)鼠標(biāo)拖動(dòng)時(shí),計(jì)算窗口的新位置(winfo_x+ 鼠標(biāo)移動(dòng)的偏移量),并用geometry方法更新窗口位置。- 通過檢查
event.widget是否為close_button,我們確保在關(guān)閉按鈕上按住時(shí)不會(huì)觸發(fā)拖動(dòng),保證按鈕功能正常。
2. 程序入口
if __name__ == "__main__": 語句塊創(chuàng)建 ChineseClock 實(shí)例,并啟動(dòng) Tkinter 的事件循環(huán) mainloop(),程序開始運(yùn)行并等待用戶交互。
完整代碼
import tkinter as tk
from datetime import datetime
from lunardate import LunarDate
class ChineseClock:
def __init__(self):
# 時(shí)辰養(yǎng)生提示字典
self.shichen_dict = {
("子時(shí)", "23:00-01:00"): "膽經(jīng)運(yùn)行,及時(shí)入睡養(yǎng)陽氣",
("丑時(shí)", "01:00-03:00"): "肝經(jīng)運(yùn)行,深度睡眠助排毒",
("寅時(shí)", "03:00-05:00"): "肺經(jīng)運(yùn)行,保持溫暖忌寒涼",
("卯時(shí)", "05:00-07:00"): "大腸經(jīng)運(yùn)行,起床飲水促排毒",
("辰時(shí)", "07:00-09:00"): "胃經(jīng)運(yùn)行,營養(yǎng)早餐要溫食",
("巳時(shí)", "09:00-11:00"): "脾經(jīng)運(yùn)行,適當(dāng)活動(dòng)助運(yùn)化",
("午時(shí)", "11:00-13:00"): "心經(jīng)運(yùn)行,小憩養(yǎng)神忌過勞",
("未時(shí)", "13:00-15:00"): "小腸經(jīng)運(yùn)行,補(bǔ)充水分助吸收",
("申時(shí)", "15:00-17:00"): "膀胱經(jīng)運(yùn)行,多喝溫水促代謝",
("酉時(shí)", "17:00-19:00"): "腎經(jīng)運(yùn)行,少鹽飲食護(hù)腎氣",
("戌時(shí)", "19:00-21:00"): "心包經(jīng)運(yùn)行,放松心情宜休閑",
("亥時(shí)", "21:00-23:00"): "三焦經(jīng)運(yùn)行,準(zhǔn)備入睡排煩惱"
}
# 農(nóng)歷月份轉(zhuǎn)換
self.lunar_months = ["正月", "二月", "三月", "四月", "五月", "六月",
"七月", "八月", "九月", "十月", "冬月", "臘月"]
# 創(chuàng)建主窗口
self.root = tk.Tk()
self.root.title("中醫(yī)養(yǎng)生時(shí)鐘")
self.root.attributes('-topmost', True)
self.root.overrideredirect(True) # 無邊框窗口
self.root.config(bg='black')
# 拖動(dòng)相關(guān)變量
self._drag_start_x = 0
self._drag_start_y = 0
# 創(chuàng)建界面組件
self.create_widgets()
# 綁定拖動(dòng)事件
self.bind_drag_events()
# 初始位置
self.set_initial_position()
# 啟動(dòng)時(shí)間更新
self.update_time()
def close_window(self):
"""關(guān)閉窗口的方法"""
print("正在關(guān)閉時(shí)鐘...")
self.root.destroy()
def bind_drag_events(self):
"""
為窗口主體內(nèi)容綁定拖動(dòng)事件。
避免對關(guān)閉按鈕等特定組件綁定拖動(dòng)事件,以確保它們能被正常點(diǎn)擊。
"""
# 對于 main_frame 內(nèi)的每個(gè)子組件
for child in self.main_frame.winfo_children():
# 如果不是關(guān)閉按鈕,則綁定拖動(dòng)事件
if child != self.close_button:
child.bind("<ButtonPress-1>", self.start_drag)
child.bind("<B1-Motion>", self.on_drag)
# 主窗口本身也可以拖動(dòng)(只要不在關(guān)閉按鈕上按下的情況下)
self.root.bind("<ButtonPress-1>", self.start_drag)
self.root.bind("<B1-Motion>", self.on_drag)
def start_drag(self, event):
"""記錄拖動(dòng)起始位置,但排除在關(guān)閉按鈕上的操作"""
# 檢查事件是否發(fā)生在關(guān)閉按鈕上
if str(event.widget) == str(self.close_button):
# 如果在關(guān)閉按鈕上按下,則不進(jìn)行任何拖動(dòng)相關(guān)的操作
return
# 否則,記錄拖動(dòng)的初始相對位置(相對于被點(diǎn)擊的widget)
self._drag_start_x = event.x
self._drag_start_y = event.y
def on_drag(self, event):
"""處理拖動(dòng)事件"""
x = self.root.winfo_x() + (event.x - self._drag_start_x)
y = self.root.winfo_y() + (event.y - self._drag_start_y)
self.root.geometry(f"+{x}+{y}")
def set_initial_position(self):
"""設(shè)置初始位置在右上角"""
screen_width = self.root.winfo_screenwidth()
self.root.geometry(f"+{screen_width - 600}+20")
def create_widgets(self):
"""創(chuàng)建界面組件"""
# 字體配置
time_font = ('微軟雅黑', 26, 'bold') # 公歷時(shí)間
weekday_font = ('微軟雅黑', 22, 'bold') # 星期
lunar_font = ('微軟雅黑', 18) # 農(nóng)歷
shichen_font = ('微軟雅黑', 16) # 時(shí)辰提示
# 創(chuàng)建一個(gè)Frame來容納主要內(nèi)容
self.main_frame = tk.Frame(self.root, bg='black')
self.main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# 關(guān)閉按鈕 - 優(yōu)化版
# 使用較小的尺寸,避免遮擋文本
self.close_button = tk.Button(
self.root,
text="×",
command=self.close_window,
font=('Arial', 6, 'bold'), # 更清晰的字體
fg='white',
bg='red',
bd=0,
width=1,
height=1,
relief='flat' # 去除按鈕立體感
)
# 精確放置:x=-15, y=10 使按鈕更靠近右上角,且不遮擋時(shí)間
self.close_button.place(relx=1.0, rely=0.0, anchor='ne', x=-2, y=2)
# 公歷時(shí)間標(biāo)簽
self.gregorian_label = tk.Label(
self.main_frame,
font=time_font,
fg='#00FF00', # 綠色
bg='black'
)
self.gregorian_label.pack(pady=(0, 5))
# 星期標(biāo)簽
self.weekday_label = tk.Label(
self.main_frame,
font=weekday_font,
fg='#FFFF00', # 黃色
bg='black'
)
self.weekday_label.pack(pady=(0, 10))
# 農(nóng)歷時(shí)間標(biāo)簽
self.lunar_label = tk.Label(
self.main_frame,
font=lunar_font,
fg='#FFD700', # 金色
bg='black'
)
self.lunar_label.pack(pady=(0, 10))
# 時(shí)辰提示標(biāo)簽
self.shichen_label = tk.Label(
self.main_frame,
font=shichen_font,
fg='#FF6347', # 深紅
bg='black',
wraplength=400, # 文本自動(dòng)換行
justify='center' # 居中對齊
)
self.shichen_label.pack(pady=(0, 10))
# 添加底部裝飾線(可選)
separator = tk.Frame(self.main_frame, height=2, bg='#333333', width=400)
separator.pack(pady=(0, 5))
def get_shichen(self):
"""獲取當(dāng)前時(shí)辰及提示"""
current_hour = datetime.now().hour
for (name, time_range), tip in self.shichen_dict.items():
start = int(time_range.split("-")[0].split(":")[0])
end = int(time_range.split("-")[1].split(":")[0])
# 處理跨天時(shí)辰(子時(shí))
if start > end:
if current_hour >= start or current_hour < end:
return f"{name}({time_range})· {tip}"
elif start <= current_hour < end:
return f"{name}({time_range})· {tip}"
return ""
def get_lunar_date(self):
"""獲取格式化農(nóng)歷日期"""
now = datetime.now()
lunar_date = LunarDate.fromSolarDate(now.year, now.month, now.day)
# 轉(zhuǎn)換月份
month_str = self.lunar_months[lunar_date.month - 1]
if lunar_date.isLeapMonth:
month_str = "閏" + month_str
# 轉(zhuǎn)換日期
day_str = self.number_to_chinese(lunar_date.day)
return f"農(nóng)歷:{lunar_date.year}年{month_str}{day_str}"
def number_to_chinese(self, num):
"""數(shù)字轉(zhuǎn)中文日期(1-30)"""
chinese_days = ["初一", "初二", "初三", "初四", "初五",
"初六", "初七", "初八", "初九", "初十",
"十一", "十二", "十三", "十四", "十五",
"十六", "十七", "十八", "十九", "二十",
"廿一", "廿二", "廿三", "廿四", "廿五",
"廿六", "廿七", "廿八", "廿九", "三十"]
return chinese_days[num - 1]
def update_time(self):
"""更新時(shí)間顯示"""
now = datetime.now()
# 公歷時(shí)間
gregorian_text = now.strftime(f"北京時(shí)間:%Y-%m-%d %H:%M:%S")
self.gregorian_label.config(text=gregorian_text)
# 星期
weekdays_zh = ["星期一", "星期二", "星期三",
"星期四", "星期五", "星期六", "星期日"]
weekday_str = weekdays_zh[now.weekday()]
self.weekday_label.config(text=weekday_str)
# 農(nóng)歷時(shí)間
self.lunar_label.config(text=self.get_lunar_date())
# 時(shí)辰提示
self.shichen_label.config(text=self.get_shichen())
# 每秒更新
self.root.after(1000, self.update_time)
if __name__ == "__main__":
clock = ChineseClock()
clock.root.mainloop()到此這篇關(guān)于基于Python打造一個(gè)你的專屬中醫(yī)養(yǎng)生桌面時(shí)鐘的文章就介紹到這了,更多相關(guān)Python桌面時(shí)鐘內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python?Scala函數(shù)與訪問修辭符實(shí)例詳解
這篇文章主要為大家介紹了python?Scala函數(shù)與訪問修辭符實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Python中實(shí)現(xiàn)switch功能實(shí)例解析
這篇文章主要介紹了Python中實(shí)現(xiàn)switch功能實(shí)例解析,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01
初步介紹Python中的pydoc模塊和distutils模塊
這篇文章主要介紹了Python中的pydoc模塊和distutils模塊,本文來自于IBM官方開發(fā)者技術(shù)文檔,需要的朋友可以參考下2015-04-04
詳解在Python程序中解析并修改XML內(nèi)容的方法
這篇文章主要介紹了在Python程序中解析并修改XML內(nèi)容的方法,依賴于解析成樹狀結(jié)構(gòu)后的節(jié)點(diǎn)進(jìn)行修改,需要的朋友可以參考下2015-11-11
Python使用pip通過命令設(shè)置國內(nèi)鏡像源的三種方式
在使用?pip?安裝?Python?模塊時(shí),默認(rèn)的國外鏡像源可能會(huì)導(dǎo)致下載速度緩慢甚至超時(shí),為了解決這個(gè)問題,可以使用國內(nèi)的鏡像源來加速下載,以下是常用的國內(nèi)鏡像源以及臨時(shí)和永久的配置方法,需要的朋友可以參考下2025-08-08

