Problem z "animacją" w Tkinter

0

Witam!

Mam aplikację w python3 + tkinter, w której chciałem zrobić coś na wzór animacji. Mam na Canvasie 4 okręgi, które zmieniają kolor 1 za 2gim. Tzn. Kolorujemy 1wszy na zielono, sleep 0.25, kolorujemy wszystkie na czarno. Potem kolorujemy 2gi, sleep itd...

Problem jest w tym, że pętla for jakby "freezuje" mi pętle, przez co program po kliknięciu przycisku zawiesza na kilka sekund i nie pokazuje żadnego efektu. Domyślam się, że trzeba będzie tutaj użyć modułu threading, ale nie za bardzo wiem jak się za to zabrać. Jakieś porady :) ?

Kod poniżej

from tkinter import *
import time


class MyGUI(Tk):

    def __init__(self):
        Tk.__init__(self)
        self.geometry('450x500')
        self.resizable(False, False)
        self.title("Test123")

        submit1 = Button(self, text ="START", command = self.start_animation)
        submit1.pack()

        self.c = Canvas(self, height="400", width="430", bg="white")
        self.c.pack()

        self.n1 = self.c.create_oval(10, 20, 110, 120, width="5")
        self.n2 = self.c.create_oval(250, 20, 350, 120, width="5")
        self.n3 = self.c.create_oval(10, 260, 110, 360, width="5")
        self.n4 = self.c.create_oval(250, 260, 350, 360, width="5")

        self.mainloop()

    def start_animation(self):
        self.colour_all_to_black()

        for x in range(10):
            good = x%4

            if good == 0:
                self.c.itemconfig(self.n1, outline="chartreuse2")
                self.colour_all_to_black()
            elif good == 1:
                self.c.itemconfig(self.n2, outline="chartreuse2")
                self.colour_all_to_black()
            elif good == 2:
                self.c.itemconfig(self.n3, outline="chartreuse2")
                self.colour_all_to_black()
            else:
                self.c.itemconfig(self.n4, outline="chartreuse2")
                self.colour_all_to_black()

    def colour_all_to_black(self):
        time.sleep(0.25)
        self.c.itemconfig(self.n1, outline="black")
        self.c.itemconfig(self.n2, outline="black")
        self.c.itemconfig(self.n3, outline="black")
        self.c.itemconfig(self.n4, outline="black")
        time.sleep(0.25)



if __name__ == '__main__':
    my_gui = MyGUI() ```
0

Jak podzielisz animację na poszczególne kroki to możesz użyć metody after.
Tu jakieś (pierwsze z brzegu) przykłady użycia:
https://www.geeksforgeeks.org/python-after-method-in-tkinter/
https://riptutorial.com/tkinter/example/22870/-after--

0

Na jakie kroki mam to podzielić bo nie bardzo rozumiem? W sensie każdy "if" ma być oddzielną funkcją?

1

Przykładowo tak:

def animation(self, x):
    if x>=10:
        return

    good = x%4

    if good == 0:
        self.c.itemconfig(self.n1, outline="chartreuse2")
    ...
    else:
        self.c.itemconfig(self.n4, outline="chartreuse2")

    self.after(250, self.colour_all_to_black)
    self.after(500, lambda: self.animation(x+1))

Wywołaj przez self.animation(0).

1 użytkowników online, w tym zalogowanych: 0, gości: 1