【问题标题】:Why isn't the fade in animation working but the fade out animation works?为什么淡入淡出动画不起作用但淡出动画起作用?
【发布时间】:2020-12-06 22:31:09
【问题描述】:

我是 python 新手,我想出了一个关于如何在 python 中使用 tkinter 和 time 模块制作简单淡入淡出动画的想法。我为程序定义了两个动画:一个淡入,另一个淡出。淡出动画效果完美,完全符合我的要求,但是,动画淡入效果根本不起作用。在 while 循环完成之前,该程序几乎不会出现。我做错了什么还是不可能在 python tkinter 中创建淡入淡出效果? 这是我的代码 sn-p:

from tkinter import *
import time

root = Tk()
transparency = 0
while transparency <= 1:
    transparency += 0.1
    root.wm_attributes("-alpha", transparency)
    time.sleep(0.03)


def fade():
    t = 1
    while t > 0:
        t -= 0.1
        root.wm_attributes("-alpha", t)
        time.sleep(0.03)
    root.destroy()


btn = Button(root, text='fade exit', command=fade).pack()
root.mainloop()

【问题讨论】:

  • 简单的解决方法是在time.sleep(...) 之前添加root.update()

标签: python animation tkinter fadein fadeout


【解决方案1】:

不要使用while 循环和time,而是使用after(millis, function) 和递归。

奖金:

  • 使用函数参数自定义淡化效果和行为
  • 这不会阻止根更新
  • 一切都被封装了
  • 这些功能可用于任何Toplevel 窗口
  • applyFades 一次通话即可管理一切

如果您绝对需要将这些功能附加到 Button,只需像这样分配 command 参数:command=lambda: fadeOut(root)

window.py

''' Fade In
    @window ~ the window to affect
    @millis ~ the amount of milliseconds to wait before next recursion
    @inc    ~ the amount to increment alpha on each recursion
'''
def fadeIn(window, millis:int=50, inc:float=0.1):
    alpha = float(window.attributes('-alpha')) + inc
    window.attributes('-alpha', alpha)
    if alpha < 1:
        window.after(millis, lambda: fadeIn(window, millis, inc))
    else:
        window.attributes('-alpha', 1.0)


''' Fade Out
    @window, @millis ~ see: Fade In
    @dec     ~ the amount to decrement alpha on each recursion
    @destroy ~ True|False destroy the window when effect is complete
'''
def fadeOut(window, millis:int=50, dec:float=0.1, destroy:bool=True):
    alpha = float(window.attributes('-alpha')) - dec
    window.attributes('-alpha', alpha)
    if alpha > 0:
        window.after(millis, lambda: fadeOut(window, millis, dec, destroy))
    else:
        window.attributes('-alpha', 0.0)
        if destroy:
            window.destroy()
            
            
''' Assign All Fades In One Call
    @window, @millis, @inc  ~ see: Fade In
    @dec, @destroy          ~ see: Fade Out
    @close ~ True|False add fadeOut effect to window close button
'''
def applyFades(window, millis:int=50, inc:float=0.1, dec:float=0.1, destroy:bool=True, close:bool=True):
    window.attributes('-alpha', 0.0)
    window.after(millis, lambda: fadeIn(window, millis, inc))
    if close:
        window.protocol("WM_DELETE_WINDOW", lambda: fadeOut(window, millis, dec, destroy))

        

main.py

import tkinter as tk
import window as win
        
  
root = tk.Tk()

win.applyFades(root) 

root.mainloop()

【讨论】:

  • 嗨,@迈克尔!希望你有一个美好的一天!非常感谢您提供代码 sn-p!它对我有用!但是,我真的很想知道为什么我的代码不起作用。仅仅是因为我使用了 time.sleep 还是我的整个算法都是错误的?我真的很想知道。谢谢!
  • @Omid Ketabollahi 是的。 while 循环停止 mainloop 运行,直到它完成。本质上,您阻止了 gui 更新。需要sleep时使用after()
【解决方案2】:

让我们看看你的脚本做了什么。在开始时分配root = Tk(),它启动一个 tcl/tk 解释器并创建一个根窗口。然后它控制它的 opacity 属性淡入。之后,一个 Button 小部件被放置在具有以下属性的根窗口上:

  • 小部件顶部写有“淡出退出”文本
  • 它等待鼠标单击并在控制根窗口的不透明度属性后淡出。

最后,root.mainloop() 代替了

while True:
    root.update_idletasks()
    root.update()

您可能会注意到在您的根窗口未更新时正在创建“淡入”按钮。这就是您无法看到实际淡入的原因。

解决方案 1. 在每次淡入样本后更新根窗口:

from tkinter import *
import time

def fade():
    t = 1
    while t > 0:
        t -= 0.1
        root.wm_attributes("-alpha", t)
        time.sleep(0.03)
    root.destroy()

root = Tk()
transparency = 0
btn = Button(root, text='fade in', command=fade)
btn.pack()

while transparency <= 1:
    transparency += 0.1
    root.wm_attributes("-alpha", transparency)
    root.update_idletasks()
    root.update()
    time.sleep(0.03)

btn.configure(text='fade exit') #I guess no new button is needed and text should be replaced only
root.mainloop()

解决方案 2. 更典型的做法是不要将tkintertime 结合使用,而是使用after 方法。查看迈克尔的答案。

【讨论】:

    猜你喜欢
    • 2012-09-25
    • 1970-01-01
    • 2019-09-24
    • 1970-01-01
    • 2015-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    相关资源
    最近更新 更多