フェードインアニメーションが機能しないのに、フェードアウトアニメーションが機能するのはなぜですか?
私はPythonを初めて使用し、tkinterとtimeモジュールを使用してPythonで簡単なフェードアニメーションを作成する方法についてこのアイデアを思いつきました。プログラムに2つのアニメーションを定義しました。1つはフェードインし、もう1つはフェードアウトします。フェードアウトアニメーションは完全に機能し、私が望むとおりに機能しますが、フェードインアニメーションはまったく機能しません。このプログラムは、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
1回の呼び出しですべてを管理します
これらの機能をに添付する必要がある場合は、次のように引数を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インタープリターを開始し、ルートウィンドウを作成するものが割り当てられます。次に、不透明度属性を制御してフェードインします。その後、ボタンウィジェットが次のプロパティを持つルートウィンドウに配置されます。
- ウィジェットの上部に「フェード出口」というテキストが書かれています
- マウスがクリックされるのを待ち、ルートウィンドウの不透明度属性を制御した後、フェードアウトします。
最後に、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