Perché l'animazione in dissolvenza non funziona ma l'animazione in dissolvenza funziona?

Aug 18 2020

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

2 MichaelGuidry Aug 18 2020 at 03:28

Invece di usare whilecicli 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 Toplevelfinestra
  • applyFades gestisce tutto in una chiamata

Se è assolutamente necessario collegare queste caratteristiche ad una Button, è sufficiente assegnare l' commandargomento 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()
2 mathfux Aug 18 2020 at 03:34

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 tkinterin combinazione con timee utilizzare il aftermetodo. Controlla la risposta di Michael.