Perché l'animazione in dissolvenza non funziona ma l'animazione in dissolvenza funziona?
Sono nuovo in Python e mi è venuta questa idea su come creare una semplice animazione di dissolvenza in Python usando tkinter e il modulo time . Ho definito due animazioni per il programma: una in dissolvenza in entrata e l'altra in dissolvenza in chiusura. L'animazione in dissolvenza funziona perfettamente ed esattamente come voglio che sia, tuttavia, l'animazione in dissolvenza non funziona affatto. Il programma praticamente non viene visualizzato fino al termine del ciclo while. Sto facendo qualcosa di sbagliato o è semplicemente impossibile creare una dissolvenza in effetto in python tkinter? Ecco il mio frammento di codice:
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()
Risposte
Invece di usare while
cicli e time
, usa after(millis, function)
e ricorsione.
bonus:
- utilizzare gli argomenti della funzione per personalizzare l'effetto e il comportamento della dissolvenza
- questo non bloccherà l'aggiornamento della radice
- tutto è incapsulato
- queste funzioni possono essere utilizzate su qualsiasi
Toplevel
finestra applyFades
gestisce tutto in una chiamata
Se è assolutamente necessario collegare queste caratteristiche ad una Button
, è sufficiente assegnare l' command
argomento in questo modo: 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()
Vediamo cosa fa lo script. All'inizio root = Tk()viene assegnato che avvia un interprete tcl / tk e crea una finestra di root. Quindi controlla il suo attributo di opacità in dissolvenza in apertura. Dopodiché un widget Button viene posizionato nella finestra principale che ha queste proprietà:
- un testo "fade exit" è scritto in alto sul widget
- attende un clic del mouse e dopo aver controllato l'attributo di opacità di una finestra principale per dissolversi.
Infine, root.mainloop()è un sostituto per
while True:
root.update_idletasks()
root.update()
Potresti prestare attenzione al fatto che il pulsante "dissolvenza in apertura" viene creato nel momento in cui la tua finestra principale non è aggiornata. Questo è un motivo per cui non sei in grado di vedere l'effettiva dissolvenza in entrata.
Soluzione 1. Aggiornamento della finestra principale dopo ogni campione di dissolvenza in apertura:
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()
Soluzione 2. È più tipico non utilizzare tkinter
in combinazione con time
e utilizzare il after
metodo. Controlla la risposta di Michael.