当前位置:首页>python>Python Tkinter+Turtle 古诗樱花树(诗词随风飘落效果)

Python Tkinter+Turtle 古诗樱花树(诗词随风飘落效果)

  • 2026-10-11 06:56:38
Python Tkinter+Turtle 古诗樱花树(诗词随风飘落效果)

Python Tkinter+Turtle 古诗樱花树(诗词随风飘落效果)

整体效果: 黑色夜空樱花大树、树枝自动生长;自定义古诗存入词库,诗句拆分逐行化作花瓣随风飘散、缓慢下坠;保留夜空烟花动画、右侧控制面板:切换诗词库、飘落速度、文字大小、背景主题、清空诗句;文字永久置顶不会被樱花/烟花遮挡。

完整可运行源码

import turtleimport randomimport timefrom PIL import Image, ImageTkimport tkinter as tkfrom tkinter import ttk, colorchooser, fontfrom time import sleepfrom random import choice, uniform, randintfrom math import sin, cos, radians# 全局物理参数GRAVITY = 0.05WIND_POWER = 0.12# 风力大小,控制诗句横向飘动幅度colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple','seagreen', 'indigo', 'cornflowerblue']# 多套经典古诗词库POEM_LIB = {"唐诗精选": ["床前明月光,疑是地上霜","举头望明月,低头思故乡","春眠不觉晓,处处闻啼鸟","夜来风雨声,花落知多少","白日依山尽,黄河入海流","欲穷千里目,更上一层楼"    ],"宋词婉约": ["人有悲欢离合,月有阴晴圆缺","但愿人长久,千里共婵娟","昨夜西风凋碧树,独上高楼","衣带渐宽终不悔,为伊消得人憔悴","无可奈何花落去,似曾相识燕归来"    ],"山水田园": ["空山新雨后,天气晚来秋","明月松间照,清泉石上流","采菊东篱下,悠然见南山","绿树村边合,青山郭外斜"    ]}# 背景配色方案THEME_BG = {"纯黑夜空": "#000000","深邃星空蓝": "#050520","暗夜紫罗兰": "#120522","静谧午夜绿": "#001a1a"}# 全局变量poem_falling_items = []  # 飘落诗词文字对象current_bg = "#000000"root = Nonecanvas = Noneturtle_screen = Nonepen = Noneafter_id = Nonefall_speed = 1.0# 飘落速度倍率current_poem_group = "唐诗精选"# ---------------------- 樱花树干绘制函数 ----------------------defTree(branch, t):    time.sleep(0.0004)if branch > 3:if8 <= branch <= 12:            t.color('snow'if random.randint(0, 2) == 0else'lightcoral')            t.pensize(branch / 3)elif branch < 8:            t.color('snow'if random.randint(0, 1) == 0else'lightcoral')            t.pensize(branch / 2)else:            t.color('sienna')            t.pensize(branch / 10)        t.forward(branch)        a = 1.5 * random.random()        t.right(20 * a)        b = 1.5 * random.random()        Tree(branch - 10 * b, t)        t.left(40 * a)        Tree(branch - 10 * b, t)        t.right(20 * a)        t.up()        t.backward(branch)        t.down()# 原生樱花花瓣defPetal(m, t):for i in range(m):        a = 200 - 400 * random.random()        b = 10 - 20 * random.random()        t.up()        t.forward(b)        t.left(90)        t.forward(a)        t.down()        t.color('lightcoral')        t.circle(1)        t.up()        t.backward(a)        t.right(90)        t.backward(b)# ---------------------- 飘落诗词文字粒子类(带风力+重力) ----------------------classPoemText:def__init__(self, cv, text_content, size=14):        self.cv = cv# 起始位置:樱花树冠区域随机生成        self.x = randint(150, 600)        self.y = randint(80, 260)        self.text = text_content        self.size = size# 下落速度 + 随机横向风力        self.vy = uniform(0.6, 1.3) * fall_speed        self.vx = uniform(-WIND_POWER, WIND_POWER)# 字体样式        font_style = font.Font(family="楷体", size=self.size)        self.text_id = cv.create_text(            self.x, self.y, text=self.text, font=font_style,            fill="#ffdddd", anchor=tk.CENTER        )        self.life = 0        self.max_life = randint(220, 380)  # 文字存活帧数defupdate(self):# 重力下坠        self.y += self.vy# 风力左右飘忽        self.x += self.vx# 微风随机扰动        self.vx += uniform(-0.03, 0.03)        self.life += 1# 更新坐标        self.cv.coords(self.text_id, self.x, self.y)# 文字置顶,不被烟花樱花遮挡        self.cv.tag_raise(self.text_id)defis_dead(self):# 落地超时/超出底部销毁return self.y > 510or self.life > self.max_life# ---------------------- 烟花粒子系统 ----------------------classParticle:def__init__(self, canvas, idx, total, explosion_speed, x=0., y=0., vx=0., vy=0., size=2., color='red', lifespan=2):        self.id = idx        self.x = x        self.y = y        self.initial_speed = explosion_speed        self.vx = vx        self.vy = vy        self.total = total        self.age = 0        self.color = color        self.cv = canvas        self.cid = self.cv.create_oval(x - size, y - size, x + size, y + size, fill=self.color)        self.lifespan = lifespandefupdate(self, dt):        self.age += dtif self.alive() and self.expand():            move_x = cos(radians(self.id * 360 / self.total)) * self.initial_speed            move_y = sin(radians(self.id * 360 / self.total)) * self.initial_speed            self.cv.move(self.cid, move_x, move_y)            self.vx = move_x / (float(dt) * 1000)elif self.alive():            move_x = cos(radians(self.id * 360 / self.total))            self.cv.move(self.cid, self.vx + move_x, self.vy + GRAVITY * dt)            self.vy += GRAVITY * dtelif self.cid isnotNone:            self.cv.delete(self.cid)            self.cid = Nonedefexpand(self):return self.age <= 1.2defalive(self):return self.age <= self.lifespan# 烟花循环动画defsimulate_firework(canvas):global after_idifnot root.winfo_exists():return    start_time = time.time()    explode_list = []    wait_time = randint(25, 120)    firework_num = randint(4, 8)for _ in range(firework_num):        particle_group = []        x = randint(50, 550)        y = randint(40, 140)        speed = uniform(0.4, 1.4)        size = uniform(0.4, 2.6)        color = choice(colors)        boom_speed = uniform(0.2, 0.9)        total_p = randint(8, 45)for i in range(1, total_p):            p = Particle(                canvas=canvas, idx=i, total=total_p, explosion_speed=boom_speed,                x=x, y=y, vx=speed, vy=speed, color=color, size=size, lifespan=uniform(0.5, 1.6)            )            particle_group.append(p)        explode_list.append(particle_group)    total_duration = 0.0while total_duration < 1.6:        sleep(0.01)        now = time.time()        delta = now - start_time        start_time = nowfor group in explode_list:for p in group:                p.update(delta)        canvas.update_idletasks()        total_duration += delta    after_id = root.after(wait_time, simulate_firework, canvas)# ---------------------- 诗词随风飘动主循环 ----------------------defpoem_fall_loop():# 随机新增一句诗词飘落if randint(0, 35) == 0:        poem_sentence = choice(POEM_LIB[current_poem_group])        new_text = PoemText(canvas, poem_sentence, size=poem_size_var.get())        poem_falling_items.append(new_text)# 更新所有飘落诗句    del_list = []for idx, item in enumerate(poem_falling_items):        item.update()if item.is_dead():            canvas.delete(item.text_id)            del_list.append(idx)# 倒序删除,防止索引错乱for idx in reversed(del_list):del poem_falling_items[idx]    root.after(35, poem_fall_loop)# ---------------------- 右侧控制面板逻辑 ----------------------# 切换背景defchange_bg_theme(event):global current_bg    sel = theme_combo.get()    current_bg = THEME_BG[sel]    canvas.config(bg=current_bg)    turtle_screen.screensize(bg=current_bg)# 切换诗词库defchange_poem_lib(event):global current_poem_group    current_poem_group = poem_lib_combo.get()# 调整飘落速度defset_fall_speed(val):global fall_speed    fall_speed = float(val)# 清空所有飘落诗句defclear_all_poem():for item in poem_falling_items:        canvas.delete(item.text_id)    poem_falling_items.clear()# 关闭窗口defclose_window():global after_idif after_id isnotNone:        root.after_cancel(after_id)    root.quit()# ==================== 界面布局 ====================if __name__ == '__main__':    root = tk.Tk()    root.title("古诗樱花树|诗词随风飘落+夜空烟花")    root.geometry("1120x580")    root.resizable(False, False)# 左右水平分栏    main_pane = ttk.PanedWindow(root, orient=tk.HORIZONTAL)    main_pane.pack(fill=tk.BOTH, expand=True, padx=6, pady=6)# 左侧绘图区    frame_left = ttk.Frame(main_pane)    main_pane.add(frame_left, weight=3)    canvas = tk.Canvas(frame_left, width=760, height=530, bg="#000000")    canvas.pack()# Turtle嵌入画布绘制樱花树    turtle_screen = turtle.TurtleScreen(canvas)    pen = turtle.RawTurtle(turtle_screen)    pen.hideturtle()    pen.getscreen().tracer(6, 0)    turtle_screen.screensize(bg="#000000")    pen.left(90)    pen.up()    pen.backward(160)    pen.down()    pen.color('sienna')# 绘制樱花树与基础花瓣    Tree(62, pen)    Petal(220, pen)# 右侧控制面板    frame_right = ttk.Frame(main_pane, width=320)    main_pane.add(frame_right, weight=1)    row = 0# 标题    ttk.Label(frame_right, text="🌸 古诗樱花树设置", font=("微软雅黑",13,"bold")).grid(row=row, column=0, columnspan=2, pady=10)    row += 1# 背景主题    ttk.Label(frame_right, text="背景夜空主题").grid(row=row, column=0, columnspan=2)    row += 1    theme_combo = ttk.Combobox(frame_right, values=list(THEME_BG.keys()), state="readonly", width=24)    theme_combo.current(0)    theme_combo.bind("<<ComboboxSelected>>", change_bg_theme)    theme_combo.grid(row=row, column=0, columnspan=2, pady=3)    row += 2# 诗词库切换    ttk.Label(frame_right, text="诗词素材库").grid(row=row, column=0, columnspan=2)    row += 1    poem_lib_combo = ttk.Combobox(frame_right, values=list(POEM_LIB.keys()), state="readonly", width=24)    poem_lib_combo.current(0)    poem_lib_combo.bind("<<ComboboxSelected>>", change_poem_lib)    poem_lib_combo.grid(row=row, column=0, columnspan=2, pady=3)    row += 2# 诗句大小    ttk.Label(frame_right, text="诗词文字大小").grid(row=row, column=0, sticky="w")    poem_size_var = tk.IntVar(value=14)    size_spin = ttk.Spinbox(frame_right, from_=10, to=26, textvariable=poem_size_var, width=12)    size_spin.grid(row=row, column=1)    row += 2# 飘落风速滑块    ttk.Label(frame_right, text="随风飘落速度").grid(row=row, column=0, columnspan=2)    speed_slider = ttk.Scale(frame_right, from_=0.3, to=2.2, orient=tk.HORIZONTAL,                             command=set_fall_speed, resolution=0.1, length=220)    speed_slider.set(1.0)    speed_slider.grid(row=row, column=0, columnspan=2, pady=4)    row += 2# 清空诗句按钮    ttk.Button(frame_right, text="清空所有飘落诗词", command=clear_all_poem, width=22).grid(row=row, column=0, columnspan=2, pady=6)# 启动双动画:烟花 + 诗词随风飘落    root.after(120, simulate_firework, canvas)    root.after(150, poem_fall_loop)    root.protocol("WM_DELETE_WINDOW", close_window)    root.mainloop()

核心效果特点

  1. 画面主体程序启动自动绘制一棵繁茂樱花树,粉色细碎花瓣缓缓飘落;夜空随机绽放彩色烟花;
  2. 诗词随风飘散核心效果诗句从樱花树冠上方随机生成,受风力左右晃动、受重力缓缓下坠,飘到底部自动消失; 字体默认楷体古风适配诗词,淡粉色文字适配夜景;
  3. 右侧控制面板全部功能
  • 4种夜空背景一键切换
  • 三套诗词库:唐诗、宋词、山水田园诗随意切换
  • 文字字号:10~26号自由调整
  • 风速滑块:快慢可控,数值越大飘落越快、晃动越明显
  • 一键清空画面所有漂浮诗句
  1. 层级优化:诗词文字永久置顶,不会被樱花、烟花覆盖遮挡

运行前置

pip install pillow

无需额外图片,直接运行即可

自定义修改教程

  1. 新增自己的诗词修改POEM_LIB字典,仿照格式添加诗句:
POEM_LIB = {"唐诗精选": [...],"自定义诗词": ["白日放歌须纵酒", "青春作伴好还乡"]}
  1. 调整风力大小:修改顶部WIND_POWER数值
  2. 诗句颜色:找到fill="#ffdddd"替换颜色色号
  3. 飘落疏密:修改循环里randint(0, 35)数字,数字越小诗句生成越密集

最新文章

随机文章