Событийное программирование требует иного мышления, чем процедурный код.Ваше приложение работает в бесконечном цикле, извлекая события из очереди и обрабатывая их.Чтобы сделать анимацию, все, что вам нужно сделать, это поместить элементы в эту очередь в соответствующее время.
У виджетов Tkinter есть метод с именем после , который позволяет планировать выполнение функций через определенный периодвремени.Первым шагом является написание функции, которая делает один «кадр» вашей анимации.В вашем случае вы определяете анимацию как переключение между двумя цветами.Функция, которая проверяет текущий цвет, затем переключается на другой цвет - это все, что вам нужно:
def blink(rect, canvas):
current_color = canvas.itemcget(rect, "fill")
new_color = "red" if current_color == "white" else "white"
canvas.itemconfigure(rect, fill=new_color)
Теперь нам просто нужно запустить эту функцию три раза с интервалом в одну секунду:
root.after(1000, blink, rect, canv)
root.after(2000, blink, rect, canv)
root.after(3000, blink, rect, canv)
Когда вы запускаете свой основной цикл, через одну секунду цвет изменится, через следующую секунду он снова изменится, а через третью секунду он снова изменится.
Это работает для ваших очень специфических потребностей, но это не очень хорошее общее решение.Более общее решение состоит в том, чтобы вызвать blink
один раз, а затем через некоторое время blink
снова вызвать себя.blink
тогда должен нести ответственность, чтобы знать, когда прекратить мигать.Вы можете установить флаг или счетчик, чтобы отслеживать, сколько раз вы моргали.Например:
def blink(rect, canvas):
...
# call this function again in a second to
# blink forever. If you don't want to blink
# forever, use some sort of flag or computation
# to decide whether to call blink again
canvas.after(1000, blink, rect, canvas)
В качестве последнего совета я рекомендую вам определить свою программу как класс, а затем создать экземпляр этого класса.Это делает так, что вам не нужны глобальные функции, и вам не нужно передавать столько аргументов.Это не имеет значения для программы из 20 строк, но начинает иметь значение, когда вы хотите написать что-то существенное.
Например:
from tkinter import *
class MyApp(Tk):
def __init__(self):
Tk.__init__(self)
fr = Frame(self)
fr.pack()
self.canvas = Canvas(fr, height = 100, width = 100)
self.canvas.pack()
self.rect = self.canvas.create_rectangle(25, 25, 75, 75, fill = "white")
self.do_blink = False
start_button = Button(self, text="start blinking",
command=self.start_blinking)
stop_button = Button(self, text="stop blinking",
command=self.stop_blinking)
start_button.pack()
stop_button.pack()
def start_blinking(self):
self.do_blink = True
self.blink()
def stop_blinking(self):
self.do_blink = False
def blink(self):
if self.do_blink:
current_color = self.canvas.itemcget(self.rect, "fill")
new_color = "red" if current_color == "white" else "white"
self.canvas.itemconfigure(self.rect, fill=new_color)
self.after(1000, self.blink)
if __name__ == "__main__":
root = MyApp()
root.mainloop()