Почему не работает плавное исчезновение анимации, но работает плавное исчезновение?
Я новичок в python, и мне пришла в голову идея о том, как сделать простую анимацию затухания в python с помощью tkinter и модуля времени . Я определил для программы две анимации: одну для постепенного появления, а другую - для исчезновения. Анимация затухания работает отлично и именно так, как я хочу, однако анимация затухания не работает вообще. Программа практически не отображается, пока цикл while не завершится. Я что-то делаю не так или просто невозможно создать эффект затухания в python tkinter? Вот мой фрагмент кода:
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()
Ответы
Вместо использования 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()
Посмотрим, что делает ваш скрипт. В начале root = Tk()назначается, который запускает интерпретатор tcl / tk и создает корневое окно. Затем он управляет своим атрибутом непрозрачности для постепенного появления. После этого виджет Button помещается в корневое окно, которое имеет следующие свойства:
- текст 'fade exit' написан сверху на виджете
- он ждет щелчка мыши и после того, как он управляет атрибутом непрозрачности корневого окна, исчезает.
Наконец, 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. Чаще всего не использовать tkinter
в сочетании с методом, time
а использовать after
. Посмотрите ответ Майкла.