共计 5151 个字符,预计需要花费 13 分钟才能阅读完成。

python 用来表白也是很可以的,很浪漫哦。之前弄了一版我这边没有设置分组结果关闭的时候崩溃死了,后来加上了一个关闭操作。一键关闭所有的。
import tkinter as tk
import random
import threading
import time
from queue import Queue
# -------------------------- 弹窗参数 --------------------------
FIRST_WIN_WIDTH = 300
FIRST_WIN_HEIGHT = 140
FIRST_WIN_BG = '#f0f8ff' # 外层背景色
FIRST_FRAME_BG = '#fff0f5' # 内层框架色
FIRST_TEXT = 'Hi,有点想你了!'
FIRST_TEXT_FONT = ('微软雅黑', 18, 'bold')
FIRST_TEXT_COLOR = '#d85c8a'
BUTTON_TEXT = '我也想你了'
BUTTON_FONT = ('微软雅黑', 14)
BUTTON_BG = '#ffccd5'
BUTTON_FG = '#a62639'
# 随机提示窗参数
TIP_WIN_WIDTH = 250
TIP_WIN_HEIGHT = 60
TIP_COUNT = 250 # 弹窗总数
TIP_INTERVAL = 0.04 # 弹窗间隔(秒),控制总时长
# 提示文字与颜色列表
TIP_TEXT_LIST = [
'多喝水哦~', '保持微笑呀', '元气满满', '记得吃水果', '保持好心情',
'好好爱自己', '我想你了', '偷个小懒', '期待见面', '天冷加衣',
'顺顺利利', '早点休息', '烦恼消失', '别熬夜', '开心吗',
'多穿衣服', '你超棒', '别焦虑', '加油', '你很特别',
'会好的', '要自信', '笑一个', '摸鱼快乐'
]
TIP_BG_COLORS = [
'skyblue', 'lightgreen', 'lavender', 'lightyellow', 'plum',
'coral', 'bisque', 'aquamarine'
]
# -------------------------- 核心逻辑实现 --------------------------
class TipWindowManager:
"""提示窗口管理器,统一处理窗口创建逻辑"""
def __init__(self):
self.queue = Queue() # 线程通信队列
self.root = None # 主线程 Tk 实例
self.all_tip_windows = [] # 记录所有创建的提示窗口,用于统一关闭
self.producer_done = False # 标记生产者线程是否完成
self.final_popup_shown = False # 标记最终弹窗是否已显示
def create_tip_window(self, params):
"""在主线程创建单个提示窗口"""
x, y = params
window = tk.Toplevel(self.root) # 绑定到主线程 TK 实例
window.title('嘻嘻~')
# 将窗口加入列表,方便后续关闭
self.all_tip_windows.append(window)
# 确保窗口在屏幕内
screen_width = window.winfo_screenwidth()
screen_height = window.winfo_screenheight()
x = max(0, min(x, screen_width - TIP_WIN_WIDTH))
y = max(0, min(y, screen_height - TIP_WIN_HEIGHT))
window.geometry(f"{TIP_WIN_WIDTH}x{TIP_WIN_HEIGHT}+{int(x)}+{int(y)}")
# 随机内容与样式
tip_text = random.choice(TIP_TEXT_LIST)
bg_color = random.choice(TIP_BG_COLORS)
tk.Label(
window,
text=tip_text,
bg=bg_color,
font=('微软雅黑', 16),
width=30,
height=3
).pack()
window.attributes('-topmost', True)
def process_queue(self):
"""主线程循环处理队列中的窗口创建请求"""
# 处理队列中剩余的窗口创建请求
while not self.queue.empty():
params = self.queue.get()
self.create_tip_window(params)
self.queue.task_done()
# 检查:生产者线程完成 + 队列为空 + 未显示最终弹窗 → 显示最终弹窗
if self.producer_done and self.queue.empty() and not self.final_popup_shown:
self.show_final_popup()
self.final_popup_shown = True
else:
# 继续监听,直到满足条件
self.root.after(100, self.process_queue)
def start_tip_producer(self, screen_width, screen_height):
"""启动子线程生成随机窗口参数"""
def producer():
# 生成所有弹窗参数
for _ in range(TIP_COUNT):
x = random.randrange(0, screen_width - TIP_WIN_WIDTH)
y = random.randrange(0, screen_height - TIP_WIN_HEIGHT)
self.queue.put((x, y))
time.sleep(TIP_INTERVAL)
# 生产者线程完成,标记状态
self.producer_done = True
# 启动守护线程(主程序退出时自动结束)producer_thread = threading.Thread(target=producer, daemon=True)
producer_thread.start()
def start_main_loop(self, screen_width, screen_height):
"""启动主线程 TK 循环"""
self.root = tk.Tk()
self.root.withdraw() # 隐藏主窗口(仅用于事件循环)self.process_queue() # 启动队列处理
self.start_tip_producer(screen_width, screen_height)
self.root.mainloop()
def show_final_popup(self):
"""显示最终的提示弹窗,点击后关闭所有窗口"""
# 创建最终弹窗
final_win = tk.Toplevel(self.root)
final_win.title('结束啦~')
final_win.attributes('-topmost', True) # 置顶显示,确保能看到
# 弹窗居中
screen_width = final_win.winfo_screenwidth()
screen_height = final_win.winfo_screenheight()
win_width = 280
win_height = 120
x = int((screen_width - win_width) / 2)
y = int((screen_height - win_height) / 2)
final_win.geometry(f"{win_width}x{win_height}+{x}+{y}")
final_win.configure(bg='#f0f8ff')
# 内层框架
frame = tk.Frame(
final_win,
bg='#fff0f5',
relief=tk.RIDGE,
bd=3
)
frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# 核心提示文字
tk.Label(
frame,
text='我想你了,你可以关闭了',
bg='#fff0f5',
font=('微软雅黑', 18, 'bold'),
fg='#d85c8a',
pady=10
).pack()
# 关闭所有窗口的函数
def close_all_windows():
# 1. 关闭所有随机提示窗口
for win in self.all_tip_windows:
try:
win.destroy()
except Exception:
pass # 忽略已关闭的窗口
# 2. 关闭最终弹窗
final_win.destroy()
# 3. 关闭主窗口,退出程序
self.root.quit()
self.root.destroy()
# 关闭按钮(醒目设计)tk.Button(
frame,
text='关闭所有',
font=('微软雅黑', 14, 'bold'),
bg='#ff6b8b',
fg='white',
relief=tk.RAISED,
padx=20,
pady=5,
cursor='hand2',
command=close_all_windows
).pack(pady=5)
def create_first_popup(manager):
"""创建第一阶段带淡入淡出的问候弹窗"""
first_win = tk.Tk()
first_win.overrideredirect(True) # 无标题栏
first_win.attributes('-topmost', True)
first_win.attributes('-alpha', 0) # 初始透明
first_win.configure(bg=FIRST_WIN_BG)
# 居中定位
screen_width = first_win.winfo_screenwidth()
screen_height = first_win.winfo_screenheight()
x = int((screen_width - FIRST_WIN_WIDTH) / 2)
y = int((screen_height - FIRST_WIN_HEIGHT) / 2)
first_win.geometry(f"{FIRST_WIN_WIDTH}x{FIRST_WIN_HEIGHT}+{x}+{y}")
# 内层框架(模拟边框)frame = tk.Frame(
first_win,
bg=FIRST_FRAME_BG,
relief=tk.RIDGE,
bd=3
)
frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# 问候文字
tk.Label(
frame,
text=FIRST_TEXT,
bg=FIRST_FRAME_BG,
font=FIRST_TEXT_FONT,
fg=FIRST_TEXT_COLOR,
pady=10
).pack()
# 淡入动画(500ms 完成)def fade_in():
current_alpha = first_win.attributes('-alpha')
if current_alpha < 1.0:
first_win.attributes('-alpha', current_alpha + 0.1)
first_win.after(50, fade_in)
# 淡出动画(500ms 完成)def fade_out():
current_alpha = first_win.attributes('-alpha')
if current_alpha > 0:
first_win.attributes('-alpha', current_alpha - 0.1)
first_win.after(50, fade_out)
else:
first_win.destroy()
# 启动提示窗口逻辑
manager.start_main_loop(screen_width, screen_height)
# 按钮点击事件
tk.Button(
frame,
text=BUTTON_TEXT,
font=BUTTON_FONT,
bg=BUTTON_BG,
fg=BUTTON_FG,
relief=tk.FLAT,
padx=15,
pady=5,
cursor='hand2',
command=fade_out
).pack(pady=5)
fade_in() # 启动淡入
first_win.mainloop()
if __name__ == "__main__":
# 初始化管理器并启动程序
tip_manager = TipWindowManager()
create_first_popup(tip_manager)
正文完
