【开发】利用AI · 纯小白也能编写精美的电脑日历📅组件
💠前言✨
- 利用目前国内外主流的AI工具,可以编程小程序,比如打包为电脑时间日历小组件,完全不懂代码,也可以成功.
- 电脑win11系统,安装编程软件:pycharm
💠正文✨
- 去Github找一个你满意的软件,把网站扔给AI,让他根据你的需求和电脑环境进行代码提供。
- Pycharm软件,左上角的文件,需要创建新项目,环境为自定义虚拟环境,python 3.14, 如图⬇️:

- 左侧的菜单栏,选择根目录,鼠标右键,点击新建,名称根据项目自定义即可,如图⬇️:

- 代码,粘贴到右侧空白区域即可,右上角的绿色▶️按钮为实时展示成品
- 作者写了一款HTC的翻页桌面大时钟+日历📅的组件,鼠标右键还支持查看每月的日期.
- 效果如图:

- 先安装依赖包,代码如下:
pip install PyQt6 pystray Pillow borax
- 代码如下:
import sys
import os
import threading
import calendar
import winreg
from datetime import datetime
from PyQt6.QtWidgets import (
QApplication, QWidget, QLabel, QVBoxLayout, QHBoxLayout, QGridLayout,
QFrame, QStackedLayout
)
from PyQt6.QtCore import QTimer, Qt, QPoint, QSettings, pyqtSignal
from PyQt6.QtGui import QFont, QIcon
import pystray
from PIL import Image
# --- 资源路径解析(打包 exe 时的核心函数) ---
def resource_path(relative_path):
""" 获取资源的绝对路径,兼容开发环境和 PyInstaller 打包环境 """
if hasattr(sys, '_MEIPASS'):
# PyInstaller 会将资源解压到这个临时文件夹
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
# --- Borax 农历支持 ---
BORAX_AVAILABLE = False
try:
from borax.calendars.lunardate import LunarDate
BORAX_AVAILABLE = True
except:
BORAX_AVAILABLE = False
class HTCFlipClock(QWidget):
# 信号:由托盘触发,主线程执行 UI 更新
sig_apply_font = pyqtSignal(str)
def __init__(self):
super().__init__()
self.old_pos = None
self.is_calendar_mode = False
# 配置系统
self.settings = QSettings("MyStudio", "HTC_Clock_Stable_Final")
self.is_locked = self.settings.value("is_locked", False, type=bool)
self.current_font = self.settings.value("font_family", "Impact")
self.auto_start_active = False
self.init_ui()
self.load_settings()
self.check_auto_start_status()
# 绑定信号
self.sig_apply_font.connect(self.handle_font_change)
self.timer = QTimer(self)
self.timer.timeout.connect(self.refresh_display)
self.timer.start(1000)
self.refresh_display()
def init_ui(self):
self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.Tool)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
# 加载内部图标
icon_path = resource_path("clock.ico")
if os.path.exists(icon_path):
self.setWindowIcon(QIcon(icon_path))
self.main_container = QWidget(self)
self.main_container.setFixedWidth(280)
self.main_container.setStyleSheet("background-color: rgba(20, 20, 20, 245); border-radius: 15px;")
self.layout_total = QVBoxLayout(self.main_container)
self.layout_total.setContentsMargins(12, 12, 12, 12)
# 顶部日期栏
self.top_bar = QHBoxLayout()
lbl_s = "font-family: 'Microsoft YaHei'; font-size: 11px; color: #777;"
self.date_lbl = QLabel(); self.date_lbl.setStyleSheet(lbl_s)
self.week_lbl = QLabel(); self.week_lbl.setStyleSheet(f"{lbl_s} color: #FF3B30; font-weight: bold;")
self.lunar_lbl = QLabel(); self.lunar_lbl.setStyleSheet(lbl_s)
self.top_bar.addWidget(self.date_lbl); self.top_bar.addStretch(); self.top_bar.addWidget(self.week_lbl); self.top_bar.addStretch(); self.top_bar.addWidget(self.lunar_lbl)
self.layout_total.addLayout(self.top_bar)
self.view_stack = QStackedLayout()
# 时钟页
self.page_time = QWidget()
layout_time = QHBoxLayout(self.page_time)
layout_time.setContentsMargins(0, 10, 0, 0); layout_time.setSpacing(10)
self.h_card, self.h_lbl = self.create_flip_card(self.page_time)
self.m_card, self.m_lbl = self.create_flip_card(self.page_time)
layout_time.addWidget(self.h_card); layout_time.addWidget(self.m_card)
self.view_stack.addWidget(self.page_time)
# 日历页
self.page_cal = QWidget()
layout_cal_root = QVBoxLayout(self.page_cal)
layout_cal_root.setContentsMargins(0, 5, 0, 0)
self.cal_title = QLabel(); self.cal_title.setStyleSheet("color: white; font-weight: bold; font-size: 13px;")
layout_cal_root.addWidget(self.cal_title, alignment=Qt.AlignmentFlag.AlignCenter)
self.grid_layout = QGridLayout(); self.grid_layout.setSpacing(1)
layout_cal_root.addLayout(self.grid_layout)
self.view_stack.addWidget(self.page_cal)
self.layout_total.addLayout(self.view_stack)
main_vbox = QVBoxLayout(self)
main_vbox.setContentsMargins(0, 0, 0, 0)
main_vbox.addWidget(self.main_container)
def create_flip_card(self, parent):
container = QFrame(parent); container.setFixedSize(110, 115)
back = QFrame(container); back.setGeometry(5, 8, 100, 100); back.setStyleSheet("background: rgba(255, 255, 255, 15); border-radius: 6px;")
front = QFrame(container); front.setGeometry(0, 0, 110, 105); front.setStyleSheet("background: rgba(255, 255, 255, 22); border-radius: 8px; border: 1px solid rgba(255,255,255,15);")
lbl = QLabel(front); lbl.setGeometry(0, 0, 110, 105); lbl.setAlignment(Qt.AlignmentFlag.AlignCenter)
return container, lbl
def refresh_display(self):
now = datetime.now()
self.date_lbl.setText(now.strftime("%m-%d"))
self.week_lbl.setText(["周一", "周二", "周三", "周四", "周五", "周六", "周日"][now.weekday()])
if BORAX_AVAILABLE:
try:
lunar = LunarDate.from_solar_date(now.year, now.month, now.day)
self.lunar_lbl.setText(lunar.term if lunar.term else f"{lunar.strftime('%M%D')}")
except: pass
self.h_lbl.setText(now.strftime("%H"))
self.m_lbl.setText(now.strftime("%M"))
def handle_font_change(self, font_name):
self.current_font = font_name
is_bold = any(x in font_name for x in ["Bold", "Impact", "Black"])
weight = "bold" if is_bold else "normal"
clean_name = font_name.split(",")[0].replace(" Bold", "")
qss = f"color: white; font-family: '{clean_name}'; font-size: 80px; font-weight: {weight};"
self.h_lbl.setStyleSheet(qss)
self.m_lbl.setStyleSheet(qss)
self.settings.setValue("font_family", font_name)
# --- 基础功能 ---
def toggle_lock(self):
self.is_locked = not self.is_locked
self.settings.setValue("is_locked", self.is_locked)
def toggle_on_top(self):
is_top = bool(self.windowFlags() & Qt.WindowType.WindowStaysOnTopHint)
if is_top: self.setWindowFlags(self.windowFlags() & ~Qt.WindowType.WindowStaysOnTopHint)
else: self.setWindowFlags(self.windowFlags() | Qt.WindowType.WindowStaysOnTopHint)
self.show()
def check_auto_start_status(self):
try:
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Run", 0, winreg.KEY_READ)
winreg.QueryValueEx(key, "HTC_FlipClock_Ultimate")
winreg.CloseKey(key)
self.auto_start_active = True
except: self.auto_start_active = False
def toggle_auto_start(self):
try:
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Run", 0, winreg.KEY_SET_VALUE)
if not self.auto_start_active:
winreg.SetValueEx(key, "HTC_FlipClock_Ultimate", 0, winreg.REG_SZ, f'"{os.path.realpath(sys.argv[0])}"')
self.auto_start_active = True
else:
winreg.DeleteValue(key, "HTC_FlipClock_Ultimate")
self.auto_start_active = False
winreg.CloseKey(key)
except: pass
def mousePressEvent(self, event):
if not self.is_locked and event.button() == Qt.MouseButton.LeftButton:
self.old_pos = event.globalPosition().toPoint()
elif event.button() == Qt.MouseButton.RightButton:
self.is_calendar_mode = not self.is_calendar_mode
self.view_stack.setCurrentIndex(1 if self.is_calendar_mode else 0)
if self.is_calendar_mode: self.refresh_calendar_ui()
def mouseMoveEvent(self, event):
if not self.is_locked and self.old_pos:
delta = QPoint(event.globalPosition().toPoint() - self.old_pos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.old_pos = event.globalPosition().toPoint()
def refresh_calendar_ui(self):
while self.grid_layout.count():
child = self.grid_layout.takeAt(0)
if child.widget(): child.widget().deleteLater()
now = datetime.now()
self.cal_title.setText(f"{now.year}年 {now.month}月")
days = calendar.monthcalendar(now.year, now.month)
for r, week in enumerate(days):
for c, day in enumerate(week):
if day != 0:
d_lbl = QLabel(str(day))
is_today = (day == now.day)
d_lbl.setStyleSheet(f"color: {'#FF3B30' if is_today else 'white'}; font-size: 12px;")
self.grid_layout.addWidget(d_lbl, r, c, Qt.AlignmentFlag.AlignCenter)
def load_settings(self):
pos = self.settings.value("window_pos", QPoint(200, 200))
self.move(pos)
if self.settings.value("is_top", False, type=bool): self.toggle_on_top()
self.handle_font_change(self.current_font)
# --- 托盘管理 ---
def setup_tray(win):
icon_path = resource_path("clock.ico")
tray_img = Image.open(icon_path) if os.path.exists(icon_path) else Image.new('RGB', (64, 64), color='white')
def create_menu():
return pystray.Menu(
pystray.MenuItem("窗口锁定", lambda: win.toggle_lock(), checked=lambda item: win.is_locked),
pystray.MenuItem("窗口置顶", lambda: win.toggle_on_top(), checked=lambda item: bool(win.windowFlags() & Qt.WindowType.WindowStaysOnTopHint)),
pystray.MenuItem("开机自启", lambda: win.toggle_auto_start(), checked=lambda item: win.auto_start_active),
pystray.Menu.SEPARATOR,
pystray.MenuItem("字体切换", pystray.Menu(
pystray.MenuItem("Impact", lambda: win.sig_apply_font.emit("Impact"), checked=lambda item: win.current_font == "Impact"),
pystray.MenuItem("Consolas", lambda: win.sig_apply_font.emit("Consolas"), checked=lambda item: win.current_font == "Consolas"),
pystray.MenuItem("Segoe UI Bold", lambda: win.sig_apply_font.emit("Segoe UI Bold"), checked=lambda item: win.current_font == "Segoe UI Bold"),
pystray.MenuItem("微软雅黑", lambda: win.sig_apply_font.emit("Microsoft YaHei"), checked=lambda item: win.current_font == "Microsoft YaHei"),
)),
pystray.Menu.SEPARATOR,
pystray.MenuItem("退出程序", lambda: os._exit(0))
)
icon = pystray.Icon("HTCClock", tray_img, "HTC Flip Clock Stable")
icon.menu = create_menu()
icon.run()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
window = HTCFlipClock()
window.show()
threading.Thread(target=setup_tray, args=(window,), daemon=True).start()
sys.exit(app.exec())
- 由于需要图标,所以需要将.ico格式的图标命名为clock,放在clock.py的相同目录,进行打包为exe程序.
- 打包,需要利用PyInstaller依赖包,在下方的终端中,输入命令行:
pip install pyinstaller
- 开始全部打包📦,引号名称自定义,右侧的英文是你当前项目的名字,命令如下:
python -m PyInstaller --noconsole --onefile --icon=clock.ico --add-data "clock.ico;." --collect-all borax --name "HTC桌面时钟" clock.py
- 打包📦成功后,软件包exe就在dist电脑目录里面了.
💠折腾不止,热爱不停~✨
© 版权声明
文章版权归作者所有,未经允许请勿转载。


