好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 lm11159 于 2025-3-18 11:29 编辑
依据ashi876发表的[Python 原创] [Python 原创] 自制桌面时钟,原贴:https://www.52pojie.cn/thread-1992968-1-2.html
新手小白第一次用deepseek简单修改,新增了闹钟设置功能,更换背景功能(可以消除字体边毛刺),更改字体颜色功能,更换字体功能。
透明时钟V1.70版
按网友提出建议修改内容如下:
1、启动时窗口位于屏幕顶部居中位置。
2、颜色设置自动保存到配置文件,程序重启时会自动加载上次设置的颜色。
3、增加了开机自启动功能(没有测试,注意以管理员身份运行)。
https://pan.baidu.com/s/1WpMxm97xj1Pq45M2cS9ozA?pwd=52pj
提取码:52pj
# 初始化配置
self.config_path = os.path.join(os.path.expanduser("~"), ".digitalclock", "config.json")
self.load_config() # 加载用户配置
self.font_size = 56
self.alarm_time = None
self.alarm_message = "时间到了!"
self.common_fonts = ["Segoe UI", "Arial", "Consolas", "微软雅黑", "宋体"]
self.selected_font = self.common_fonts[0]
self.original_text_color = self.text_color
self.blink_count = 0
# 窗口初始化
self.setup_window()
self.create_widgets()
self.create_context_menu()
self.setup_bindings()
self.update_clock()
self.root.mainloop()
def load_config(self):
"""加载用户配置"""
default_config = {
"bg_color": "#000000",
"text_color": "#006400",
"window_pos": None
}
try:
if os.path.exists(self.config_path):
with open(self.config_path, 'r') as f:
config = json.load(f)
# 合并配置
self.bg_color = config.get("bg_color", default_config["bg_color"])
self.text_color = config.get("text_color", default_config["text_color"])
self.window_pos = config.get("window_pos", default_config["window_pos"])
else:
self.bg_color = default_config["bg_color"]
self.text_color = default_config["text_color"]
self.window_pos = default_config["window_pos"]
except Exception as e:
print(f"加载配置失败: {str(e)}")
self.bg_color = default_config["bg_color"]
self.text_color = default_config["text_color"]
self.window_pos = default_config["window_pos"]
def save_config(self):
"""保存用户配置"""
config_dir = os.path.dirname(self.config_path)
if not os.path.exists(config_dir):
os.makedirs(config_dir)
try:
# 保存当前窗口位置
if self.root.winfo_ismapped():
self.window_pos = f"+{self.root.winfo_x()}+{self.root.winfo_y()}"
with open(self.config_path, 'w') as f:
json.dump({
"bg_color": self.bg_color,
"text_color": self.text_color,
"window_pos": self.window_pos
}, f, indent=2)
except Exception as e:
print(f"保存配置失败: {str(e)}")
def setup_window(self):
"""窗口初始化"""
# 计算初始位置
screen_width = self.root.winfo_screenwidth()
screen_height = self.root.winfo_screenheight()
window_width = 400
window_height = 120
if self.window_pos:
# 使用保存的位置
self.root.geometry(f"{window_width}x{window_height}{self.window_pos}")
else:
# 默认位置:水平居中,距顶部3cm(约113像素)
pos_x = (screen_width - window_width) // 2
pos_y = int(screen_height * 0.05) # 顶部5%的位置
self.root.geometry(f"{window_width}x{window_height}+{pos_x}+{pos_y}")
self.root.config(bg=self.bg_color)
self.root.overrideredirect(True)
self.root.attributes("-topmost", True)
self.root.attributes("-transparentcolor", self.bg_color)
def create_widgets(self):
"""创建界面元素"""
self.time_font = font.Font(
family=self.selected_font,
size=self.font_size,
weight="bold"
)
self.label = tk.Label(
self.root,
text="",
bg=self.bg_color,
fg=self.text_color,
font=self.time_font
)
self.label.pack(expand=True)
def setup_bindings(self):
"""设置事件绑定"""
self.label.bind("<ButtonPress-1>", self.start_drag)
self.label.bind("<B1-Motion>", self.do_drag)
self.label.bind("<Button-3>", self.show_context_menu)
# 窗口关闭时保存配置
self.root.protocol("WM_DELETE_WINDOW", self.on_close)
def on_close(self):
"""关闭窗口事件处理"""
self.save_config()
self.root.destroy()
def create_context_menu(self):
"""创建右键菜单"""
self.menu = tk.Menu(self.root, tearoff=0)
# 字体菜单
font_menu = tk.Menu(self.menu, tearoff=0)
for f in self.common_fonts:
font_menu.add_command(label=f, command=lambda f=f: self.change_font(f))
# 颜色菜单
color_menu = tk.Menu(self.menu, tearoff=0)
color_menu.add_command(label="字体颜色", command=self.change_text_color)
color_menu.add_command(label="背景颜色", command=self.change_bg_color)
# 主菜单项
self.menu.add_cascade(label="选择字体", menu=font_menu)
self.menu.add_cascade(label="颜色设置", menu=color_menu)
self.menu.add_command(label="设置闹钟", command=self.show_alarm_dialog)
self.menu.add_command(label="字体放大", command=lambda: self.adjust_font_size(2))
self.menu.add_command(label="字体缩小", command=lambda: self.adjust_font_size(-2))
# 开机自启动
self.auto_start_var = tk.BooleanVar(value=self.is_auto_start_enabled())
self.menu.add_checkbutton(label="开机自启动",
variable=self.auto_start_var,
command=self.toggle_auto_start)
self.menu.add_separator()
self.menu.add_command(label="退出", command=self.on_close)
def is_auto_start_enabled(self):
"""检查开机自启动状态"""
try:
if platform.system() == "Windows":
import winreg
reg_path = r"Software\Microsoft\Windows\CurrentVersion\Run"
app_name = "DigitalClock"
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, reg_path) as key:
value, _ = winreg.QueryValueEx(key, app_name)
return os.path.abspath(sys.argv[0]) == value
elif platform.system() == "Linux":
autostart_path = os.path.expanduser("~/.config/autostart/digitalclock.desktop")
return os.path.exists(autostart_path)
else:
return False
except Exception:
return False
def toggle_auto_start(self):
"""切换自启动状态"""
if self.auto_start_var.get():
self.enable_auto_start()
else:
self.disable_auto_start()
def enable_auto_start(self):
"""启用自启动"""
try:
app_path = os.path.abspath(sys.argv[0])
if platform.system() == "Windows":
import winreg
reg_path = r"Software\Microsoft\Windows\CurrentVersion\Run"
app_name = "DigitalClock"
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, reg_path, 0, winreg.KEY_SET_VALUE) as key:
winreg.SetValueEx(key, app_name, 0, winreg.REG_SZ, f'"{app_path}"')
elif platform.system() == "Linux":
autostart_dir = os.path.expanduser("~/.config/autostart")
os.makedirs(autostart_dir, exist_ok=True)
desktop_file = os.path.join(autostart_dir, "digitalclock.desktop")
with open(desktop_file, "w") as f:
f.write(f"""[Desktop Entry]
Type=Application
Exec={app_path}
Hidden=false
NoDisplay=false
Name=Digital Clock
Comment=Transparent digital clock""")
os.chmod(desktop_file, 0o755)
messagebox.showinfo("提示", "开机自启动已启用")
except Exception as e:
messagebox.showerror("错误", f"操作失败: {str(e)}")
def disable_auto_start(self):
"""禁用自启动"""
try:
if platform.system() == "Windows":
import winreg
reg_path = r"Software\Microsoft\Windows\CurrentVersion\Run"
app_name = "DigitalClock"
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, reg_path, 0, winreg.KEY_SET_VALUE) as key:
winreg.DeleteValue(key, app_name)
elif platform.system() == "Linux":
autostart_path = os.path.expanduser("~/.config/autostart/digitalclock.desktop")
if os.path.exists(autostart_path):
os.remove(autostart_path)
messagebox.showinfo("提示", "开机自启动已禁用")
except Exception as e:
messagebox.showerror("错误", f"操作失败: {str(e)}")
def show_alarm_dialog(self):
"""显示闹钟设置对话框"""
dialog = tk.Toplevel(self.root)
dialog.title("设置闹钟提醒")
dialog.transient(self.root)
# 居中对话框
dialog.update_idletasks()
width = 300
height = 120
x = (dialog.winfo_screenwidth() - width) // 2
y = (dialog.winfo_screenheight() - height) // 2
dialog.geometry(f"{width}x{height}+{x}+{y}")
dialog.resizable(False, False)
# 时间输入
ttk.Label(dialog, text="时间 (HH:MM):").grid(row=0, column=0, padx=5, pady=5)
time_entry = ttk.Entry(dialog)
time_entry.grid(row=0, column=1, padx=5, pady=5)
# 提醒内容
ttk.Label(dialog, text="提醒内容:").grid(row=1, column=0, padx=5, pady=5)
msg_entry = ttk.Entry(dialog)
msg_entry.insert(0, self.alarm_message)
msg_entry.grid(row=1, column=1, padx=5, pady=5)
def save_alarm():
try:
time_str = time_entry.get()
if len(time_str) != 5 or time_str[2] != ':':
raise ValueError
hour, minute = map(int, time_str.split(':'))
if not (0 <= hour <=23 and 0 <= minute <=59):
raise ValueError
self.alarm_time = f"{hour:02d}:{minute:02d}"
self.alarm_message = msg_entry.get() or "时间到了!"
dialog.destroy()
except ValueError:
messagebox.showerror("错误", "请输入有效的HH:MM格式时间", parent=dialog)
ttk.Button(dialog, text="保存", command=save_alarm).grid(row=2, columnspan=2, pady=5)
dialog.grab_set()
def update_clock(self):
"""更新时间显示"""
current_time = time.strftime("%H:%M:%S")
current_time_short = time.strftime("%H:%M")
self.label.config(text=current_time)
# 检查闹钟
if self.alarm_time and current_time_short == self.alarm_time:
self.trigger_alarm()
self.alarm_time = None # 单次提醒
self.root.after(1000, self.update_clock)
def trigger_alarm(self):
"""触发提醒"""
messagebox.showinfo("提醒", self.alarm_message)
self.blink_count = 0
self.original_text_color = self.label.cget("fg")
self.blink_effect()
def blink_effect(self):
"""闪烁效果"""
if self.blink_count < 5:
new_color = "#FF0000" if self.blink_count % 2 == 0 else self.original_text_color
self.label.config(fg=new_color)
self.blink_count += 1
self.root.after(500, self.blink_effect)
else:
self.label.config(fg=self.original_text_color)
def change_bg_color(self):
"""修改背景颜色"""
color = colorchooser.askcolor(title="选择背景颜色")
if color[1]:
self.bg_color = color[1]
self.root.config(bg=self.bg_color)
self.label.config(bg=self.bg_color)
self.root.attributes("-transparentcolor", self.bg_color)
self.save_config()
# 自动调整字体颜色对比度
r, g, b = self._hex_to_rgb(color[1])
luminance = 0.299*r + 0.587*g + 0.114*b
if abs(luminance - self._hex_to_rgb(self.text_color)[0]) < 50:
self.text_color = "#FFFFFF" if luminance < 128 else "#000000"
self.label.config(fg=self.text_color)
self.save_config()
def _hex_to_rgb(self, hex_color):
"""16进制颜色转RGB元组"""
hex_color = hex_color.lstrip('#')
return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
def change_text_color(self):
"""修改文字颜色"""
color = colorchooser.askcolor(title="选择字体颜色")
if color[1]:
self.text_color = color[1]
self.label.config(fg=self.text_color)
self.save_config()
def change_font(self, font_name):
"""修改字体"""
try:
self.time_font.config(family=font_name)
self.selected_font = font_name
except tk.TclError:
messagebox.showerror("错误", f"字体 {font_name} 不可用")
def adjust_font_size(self, delta):
"""调整字体大小"""
self.font_size = max(10, self.font_size + delta)
self.time_font.config(size=self.font_size)
self.resize_window()
def resize_window(self):
"""根据字体大小调整窗口尺寸"""
new_width = self.font_size * 7
new_height = self.font_size * 2
x = self.root.winfo_x()
y = self.root.winfo_y()
self.root.geometry(f"{new_width}x{new_height}+{x}+{y}")
def start_drag(self, event):
"""开始拖拽窗口"""
self.drag_start = (event.x_root, event.y_root)
def do_drag(self, event):
"""处理拖拽移动"""
dx = event.x_root - self.drag_start[0]
dy = event.y_root - self.drag_start[1]
x = self.root.winfo_x() + dx
y = self.root.winfo_y() + dy
self.root.geometry(f"+{x}+{y}")
self.drag_start = (event.x_root, event.y_root)
def show_context_menu(self, event):
"""显示右键菜单"""
try:
self.menu.tk_popup(event.x_root, event.y_root)
finally:
self.menu.grab_release()
if __name__ == "__main__":
DigitalClock()[/md] |
-
-
免费评分
-
查看全部评分
|