Mengapa animasi fade in tidak berfungsi, tetapi animasi fade out berfungsi?
Saya baru mengenal python dan saya mendapatkan ide tentang cara membuat animasi pudar sederhana di python menggunakan tkinter dan modul waktu . Saya telah menetapkan dua animasi untuk program: satu untuk memudar dan yang lainnya memudar. Animasi fade out bekerja dengan sempurna dan persis seperti yang saya inginkan, namun animasi fade out tidak berfungsi sama sekali. Program ini tidak akan muncul sampai while loop selesai. Apakah saya melakukan sesuatu yang salah atau tidak mungkin membuat efek fade di python tkinter? Ini cuplikan kode saya:
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()
Jawaban
Alih-alih menggunakan while
loop dan time
, gunakan after(millis, function)
dan rekursi.
bonus:
- gunakan argumen fungsi untuk menyesuaikan efek fade dan perilaku
- ini tidak akan memblokir root dari pembaruan
- semuanya dikemas
- fungsi ini dapat digunakan di
Toplevel
jendela mana pun applyFades
mengelola semuanya dalam satu panggilan
Jika Anda benar-benar perlu melampirkan fitur ini ke Button
, hanya menetapkan command
argumen seperti ini: 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()
Mari kita lihat apa yang skrip Anda lakukan. Pada awalnya root = Tk()ditugaskan yang memulai interpreter tcl / tk dan membuat jendela root. Kemudian ia mengontrol atribut opacity untuk fade in. Setelah itu widget Button ditempatkan pada jendela root yang memiliki properti berikut:
- teks 'fade exit' tertulis di bagian atas widget
- itu menunggu klik mouse dan setelah itu mengontrol atribut opacity dari jendela root untuk memudar.
Akhirnya, root.mainloop()adalah pengganti
while True:
root.update_idletasks()
root.update()
Anda mungkin memperhatikan bahwa tombol 'fade in' sedang dibuat saat jendela root Anda tidak diperbarui. Inilah alasan mengapa Anda tidak dapat melihat fade in yang sebenarnya.
Solusi 1. Memperbarui jendela root setelah setiap sampel memudar:
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()
Solusi 2. Ini lebih umum untuk tidak digunakan tkinter
dalam kombinasi dengan time
dan menggunakan after
metode. Lihat jawaban Michael.