Matteo Secco
Matteo Secco

Reputation: 633

Tkinter: use root.after() properly

I want to create a projectile that every second move 10 pixel along his y axis using the after() function. The first attempt I've done is this:

  def muovi(self, root):
    i = 0
    while i < 10:
        i += 1
        self.parent.move(self.colpo, 0, 10)
        root.after(1000)

The problem is that it completely ignore self.parent.move(self.colpo, 0, 10) , which only works at the end of the loop. Then I tried with this:

    def muovi(self, root):
        self.parent.move(self.colpo, 0, 10)
        root.after(1000, self.muovi(root))

This time the code run like if instead of root.after(1000, self.muovi(root)) there is self.muovi(root)), so I get Recursion Error instantly.

How can let root.after() work properly?

Upvotes: 2

Views: 12398

Answers (2)

j_4321
j_4321

Reputation: 16169

Your first piece of code does not work because you haven't specified the function that will be called after 1000 ms.

And your second piece of code does not work because the second argument expected by after is a function, like for the command option of a button.

Here is an example:

from tkinter import Tk, Canvas, Button

def move():
    canvas.move(circle, 0, 10)
    root.after(1000, move) # the second argument has to be a function, not move()
    
root = Tk()

canvas = Canvas(root)
canvas.pack(fill='both', expand=True)
circle = canvas.create_oval(10,10,30,30, fill='red')

Button(root, text="Start", command=move).pack()

root.mainloop()

Upvotes: 1

Bryan Oakley
Bryan Oakley

Reputation: 386010

This code:

root.after(1000, self.muovi(root))

is functionally identical to this code:

result = self.muovi(root)
root.after(1000, result)

Do you see the problem? You are calling self.muovi and giving the result to after. Instead, you must supply a reference to self.muovi. Additional positional arguments can be used as arguments following the reference:

root.after(1000, self.muovi, root)

Upvotes: 3

Related Questions