All GUIs to work smoother they don't update/readraw window directly when you change item but after ending your function. This way it has to update window only once (when you make many changes in function) and it works smoother (it is less bliting).
If you want to use after()
to repeate move then you need after(250, left)
but you don't need for
-loop
after()
will send information 250, left
to mainloop()
and it will execute left()
after 250ms - and later you end your function so mainloop()
may update window after one move.
Minimal working code
import tkinter as tk # PEP8: `import *` is not preferred
# --- functions ---
def left(event):
move(-5, 0, 4)
def right(event):
move(5, 0, 4)
def up(event):
move(0, -5, 4)
def down(event):
move(0, 5, 4)
def move(dx, dy, n):
pic.move(mover, dx, dy)
n -= 1
if n > 0:
# repeate it again after 50ms
root.after(50, move, dx, dy, n)
# end of function so it goes back to mainloop and it can update/redraw window
# --- main ---
w = 200
h = 200
x = w/2
y = h/2
root = tk.Tk()
pic = tk.Canvas(root, width=w, height=h) # PEP8: spaces after `,`
pic.pack()
mover = pic.create_oval(x, y, x+10, y+10, fill="red") # PEP8: spaces after `,`
root.bind("<Left>", left) # PEP8: spaces after `,`
root.bind("<Right>", right)
root.bind("<Up>", up)
root.bind("<Down>", down)
root.mainloop()
If you use after(250)
or time.sleep(0.25)
to sleep then you need root.update()
to force mainloop()
to update/redraw window.
Minimal working code
import tkinter as tk # PEP8: `import *` is not preferred
# --- functions ---
def left(event):
move(-5, 0, 4)
def right(event):
move(5, 0, 4)
def up(event):
move(0, -5, 4)
def down(event):
move(0, 5, 4)
def move(dx, dy, n):
for _ in range(n):
pic.move(mover, dx, dy)
root.update() # <-- force `mainloop()` to update window
root.after(50)
#time.sleep(0.25)
# --- main ---
w = 200
h = 200
x = w/2
y = h/2
root = tk.Tk()
pic = tk.Canvas(root, width=w, height=h) # PEP8: spaces after `,`
pic.pack()
mover = pic.create_oval(x, y, x+10, y+10, fill="red") # PEP8: spaces after `,`
root.bind("<Left>", left) # PEP8: spaces after `,`
root.bind("<Right>", right)
root.bind("<Up>", up)
root.bind("<Down>", down)
root.mainloop()
BTW: Both versions have one problem - when you press many keys then it will run move for all keys at the same time so it may move in strange way. It would need variable is_moving = True/False
to control if it can move for other keys.