페이드 인 애니메이션은 작동하지 않지만 페이드 아웃 애니메이션은 작동하는 이유는 무엇입니까?

Aug 18 2020

저는 파이썬을 처음 접했고 tkinter와 time 모듈을 사용하여 파이썬 에서 간단한 페이드 애니메이션을 만드는 방법에 대한 아이디어를 생각해 냈습니다 . 프로그램에 대해 두 가지 애니메이션을 정의했습니다. 하나는 페이드 인하 고 다른 하나는 페이드 아웃합니다. 페이드 아웃 애니메이션은 내가 원하는대로 완벽하게 작동하지만 페이드 인 애니메이션은 전혀 작동하지 않습니다. 프로그램은 while 루프가 끝날 때까지 거의 나타나지 않습니다. 내가 뭘 잘못하고 있거나 파이썬 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()

답변

2 MichaelGuidry Aug 18 2020 at 03:28

while루프 및를 사용하는 대신 및 재귀를 time사용하십시오 after(millis, function).

보너스 :

  • 함수 인수를 사용하여 페이드 효과 및 동작을 사용자 정의하십시오.
  • 이것은 루트의 업데이트를 차단하지 않습니다.
  • 모든 것이 캡슐화되어 있습니다
  • 이러한 기능은 모든 Toplevel창에서 사용할 수 있습니다.
  • applyFades 한 번의 통화로 모든 것을 관리

이러한 기능을에 반드시 첨부해야하는 경우 다음 과 같이 인수 Button를 지정하면 됩니다..commandcommand=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

스크립트가 무엇을하는지 봅시다. 처음에는 root = Tk()tcl / tk 인터프리터를 시작하고 루트 창을 만드는 할당됩니다. 그런 다음 페이드 인 할 불투명도 속성을 제어합니다. 그 후 다음 속성을 가진 루트 창에 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. 사용 방법 과 tkinter병용 하지 않는 것이 일반적 입니다. Michael의 대답을 확인하십시오.timeafter