心形温馨提示墙
Python Tkinter进阶:用数学公式画一个浪漫的心形温馨提示墙
上次分享了随机弹窗的温馨提示工具后,好多小伙伴说想要更有仪式感的效果~今天就给大家升级一下——用Python的Tkinter结合数学公式,做一个心形排列的温馨提示弹窗墙!运行后100个暖心弹窗会沿着心形轨迹依次出现,最后统一淡出,浪漫又治愈,用来表白、送祝福都超合适~
一、项目效果直击
这个工具的核心亮点就是“心形排列”,具体效果如下:
轨迹浪漫:100个弹窗严格按照数学心形公式排列,完美勾勒出爱心形状
有序出现:弹窗按心形轨迹依次弹出,节奏舒缓不杂乱(可自定义出现速度)
统一退场:所有弹窗创建完成后,等待3秒会一起慢慢淡出,仪式感拉满
交互友好:点击任意弹窗可直接关闭,颜色和文案依旧随机柔和
无论是放在桌面当装饰,还是在特殊日子发给朋友,都能带来满满的惊喜~
二、核心代码深度解析
相比上次的随机弹窗,这次新增了心形坐标计算和统一淡出功能,整体结构更有趣。我们依旧从三个核心部分拆解:
1. 初始化配置:新增心形关键参数
在__init__方法中,除了保留原有的提示语、颜色库,重点新增了控制心形效果的参数:
def __init__(self):# ... 原有基础配置 ...# 心形专属参数self.heart_scale = 1.6 # 心形缩放比例(越大爱心越大)self.delay_after_last = 3 # 全部创建完成后等待几秒开始淡出self.fade_speed = 0.05 # 淡出速度(越小越慢)self.create_interval = 0.2 # 弹窗创建间隔(越大出现越慢)self.heart_y_offset = -80 # 心形Y轴偏移(负值上移,正值下移)# 屏幕中心计算(为了让心形居中)self.center_x = self.screen_width // 2self.center_y = self.screen_height // 2这些参数是实现心形效果的关键,后面会详细说明如何调整。
2. 灵魂所在:心形坐标计算(get_heart_position方法)
这是本次升级的核心!我们用笛卡尔心形线公式计算每个弹窗的位置,公式如下:
x = 16·sin³(t),y = 13·cos(t) - 5·cos(2t) - 2·cos(3t) - cos(4t)
方法中通过循环变量index计算出每个弹窗对应的t值,再代入公式得到坐标,最后经过缩放和偏移处理,确保心形居中且大小合适:
def get_heart_position(self, index):"""计算心形曲线上的精确坐标点"""t = 2 * math.pi * index / self.window_count # t从0到2π循环x = 16 * math.sin(t) ** 3y = 13 * math.cos(t) - 5 * math.cos(2 * t) - 2 * math.cos(3 * t) - math.cos(4 * t)# 缩放:根据屏幕大小调整心形尺寸scale = min(self.screen_width, self.screen_height) * 0.015 * self.heart_scale# 偏移:让心形在屏幕居中,可通过heart_y_offset微调上下位置return self.center_x + int(x * scale), self.center_y - int(y * scale) + self.heart_y_offset每一个弹窗的位置都由这个公式精准计算,这就是心形排列的秘密~
3. 弹窗创建与退场:有序出现+统一淡出
弹窗创建(create_heart_window方法):相比随机弹窗,这里做了两点调整
尺寸固定为200x100,让心形排列更整齐
坐标从
get_heart_position获取,同时增加边界校验,避免弹窗超出屏幕
统一淡出(unified_fade_out方法):这是新增的退场动画,当最后一个弹窗创建完成后,会启动一个定时器,3秒后所有弹窗一起从透明度0.93逐渐降到0,实现温柔的退场效果:
def unified_fade_out(self):"""所有窗口统一淡出关闭"""# 淡出动画:透明度从93降到0,每次减5for alpha in range(93, 0, -5):for window in self.active_windows[:]: # 切片避免循环中列表修改if window.winfo_exists():window.attributes('-alpha', alpha / 100)window.update()time.sleep(self.fade_speed)# 清理剩余窗口for window in self.active_windows[:]:if window.winfo_exists():window.destroy()self.active_windows.clear()三、自定义玩法:打造专属心形墙
掌握这些参数调整技巧,就能做出各种风格的心形墙:
1. 调整心形大小:修改self.heart_scale,值越大爱心越大(建议1.0-2.0之间,太大容易超出屏幕)
2. 改变出现速度:调整self.create_interval,0.1秒出现快,0.5秒出现慢,根据喜好选择
3. 移动心形位置:通过self.heart_y_offset微调,比如改成-100让心形上移更多,改成0则居中
4. 自定义文案:在self.tips列表中添加专属文案,比如“生日快乐🎂”“我爱你❤️”,瞬间变成表白神器
5. 更换配色:self.bg_colors里的颜色码可以换成自己喜欢的色系,比如全粉色系更浪漫
四、运行与注意事项
1. 运行方式
保存代码为heart_tips.py,直接运行即可:
import tkinter as tk
import random
import time
import threading
import mathclass HeartTipWindowManager:"""心形排列的温馨提示窗口管理器"""def __init__(self):self.root = tk.Tk()self.root.withdraw()self.active_windows = []self.windows_created = 0self.all_created = False# 配置参数self.window_count = 100self.heart_scale = 1.6self.delay_after_last = 3self.fade_speed = 0.05# 新增:窗口创建间隔(控制出现速度,数值越大越慢)self.create_interval = 0.2 # 原先是0.05-0.1,现在改为0.2左右# 新增:心形Y轴偏移量(控制上下位置,负值上移,正值下移)self.heart_y_offset = -80# 屏幕尺寸与中心计算self.screen_width = self.root.winfo_screenwidth()self.screen_height = self.root.winfo_screenheight()self.center_x = self.screen_width // 2self.center_y = self.screen_height // 2# 提示内容与颜色库self.tips = ['多喝水哦~💧', '保持微笑呀😊', '每天都要元气满满✨','记得吃水果🍎', '保持好心情🌞', '好好爱自己❤️','期待下一次见面👋', '顺顺利利🎯', '早点休息🌙','愿所有烦恼都消失🌈', '别熬夜⏰', '今天过得开心嘛🎉','天冷了,多穿衣服🧥', '保护眼睛哦👀','深呼吸放松一下🌬️', '你真棒!🎊', '一切都会好的🌻','保持积极心态⚡', '加油!🚀', '相信自己💪','今天也是美好的一天🌞', '保持耐心⏳', '慢慢来比较快🐢','你很特别🌟', '世界因你而美丽🌍', '放松一下🎵','享受当下🎯', '感恩生活🙏', '保持好奇心🔍','勇敢做自己🦁', '进步一点点📈', '温暖如春🌺','心平气和🍃', '梦想成真🎠', '快乐很简单😄','阳光总在风雨后🌦️', '坚持就是胜利🏆', '你是最棒的⭐','生活很美好🌷', '向前看👣', '温柔待人💝','珍惜当下🎁', '幸福在身边🎈']self.bg_colors = ['#FFF0F5', '#FFF8DC', '#F5FFFA', '#FFE4E1', '#FAFAD2','#FFF5EE', '#FFEFD5', '#FFE4B5', '#FAF0E6', '#FFB6C1','#FDF5E6', '#FFDAB9', '#FFFACD', '#F0E68C', '#EEE8AA']def get_heart_position(self, index):"""计算心形曲线上的精确坐标点"""t = 2 * math.pi * index / self.window_countx = 16 * math.sin(t) ** 3y = 13 * math.cos(t) - 5 * math.cos(2 * t) - 2 * math.cos(3 * t) - math.cos(4 * t)# 缩放计算scale = min(self.screen_width, self.screen_height) * 0.015 * self.heart_scale# 应用Y轴偏移,使心形上移return self.center_x + int(x * scale), self.center_y - int(y * scale) + self.heart_y_offsetdef create_heart_window(self, index):"""创建心形轨迹上的对话框)"""if self.windows_created >= self.window_count:returntry:# 窗口创建window = tk.Toplevel()self.active_windows.append(window)self.windows_created += 1# 固定窗口尺寸w, h = 200, 100x, y = self.get_heart_position(index)# 屏幕边界校验x = max(10, min(x - w // 2, self.screen_width - w - 10))y = max(10, min(y - h // 2, self.screen_height - h - 10))# 窗口基础配置window.title('温馨提示')window.geometry(f"{w}x{h}+{x}+{y}")window.resizable(False, False)window.attributes('-topmost', True, '-alpha', 0.93)# 标签创建label = tk.Label(window,text=random.choice(self.tips),bg=random.choice(self.bg_colors),fg='#5D4037',font=('微软雅黑', 11),padx=15,pady=15,wraplength=w - 30,justify='center')label.pack(expand=True, fill='both')# 点击关闭逻辑def on_click(event):if window.winfo_exists():window.destroy()if window in self.active_windows:self.active_windows.remove(window)self.check_completion()window.bind('<Button-1>', on_click)label.bind('<Button-1>', on_click)# 最后一个窗口判断if self.windows_created == self.window_count:self.all_created = Truethreading.Timer(self.delay_after_last, self.unified_fade_out).start()except:# 异常捕获if 'window' in locals() and window in self.active_windows:self.active_windows.remove(window)def unified_fade_out(self):"""所有窗口统一淡出关闭"""# 淡出动画(使用切片避免循环中列表修改)for alpha in range(93, 0, -5):for window in self.active_windows[:]:if window.winfo_exists():window.attributes('-alpha', alpha / 100)window.update()else:if window in self.active_windows:self.active_windows.remove(window)time.sleep(self.fade_speed)# 强制清理剩余窗口(避免内存泄漏)for window in self.active_windows[:]:if window.winfo_exists():window.destroy()self.active_windows.clear()self.check_completion()def check_completion(self):"""检查是否所有窗口关闭"""if not self.active_windows and self.all_created:self.root.quit()def start_heart_creation(self):"""开始创建窗口)"""def create_loop():# 按顺序创建窗口for i in range(self.window_count):self.root.after(0, self.create_heart_window, i)# 使用配置的间隔时间,控制出现速度time.sleep(random.uniform(self.create_interval * 0.8, self.create_interval * 1.2))return create_loopdef main(self):"""主程序入口"""# 启动创建线程thread = threading.Thread(target=self.start_heart_creation(), daemon=True)thread.start()# 主循环try:self.root.mainloop()except KeyboardInterrupt:passfinally:# 强制清理所有窗口for window in self.active_windows[:]:if window.winfo_exists():window.destroy()self.root.quit()def main():"""简化主函数,直接初始化运行"""HeartTipWindowManager().main()if __name__ == "__main__":main()运行后耐心等待几秒,心形会慢慢显现,全部出现后等待3秒开始统一淡出。
2. 注意事项
弹窗数量
window_count建议在50-150之间,太少心形不饱满,太多可能影响性能如果心形超出屏幕,可减小
heart_scale或调整heart_y_offset若想提前关闭,点击任意弹窗或按
Ctrl+C终止程序
五、总结
这个心形温馨提示墙,把数学公式和编程结合起来,既有趣又浪漫。不仅能锻炼Tkinter和多线程的使用能力,还能做出有温度的小工具。无论是自己用还是送给别人,都是一份特别的惊喜~
如果大家有更有创意的扩展想法,比如让弹窗旋转出现、添加背景音乐,或者用其他曲线(比如星星、月亮)排列,都可以在评论区交流~希望这个小项目能给你带来灵感,咱们下次见!💖
