Reputation: 45
I have a program where I need to move an image object every time the mainloop() loops. I haven't tried doing much, mostly because I don't know where to start. I made a dummy version of my project that simulates the issue I'm having.
from tkinter import *
window = tk.Tk()
window.geometry('%ix%i+400+0' % (500, 600))
canvas = Canvas(window, width=500, height=600, bg='white')
canvas.pack()
w, x, y, z = 300, 300, 200, 200
x = canvas.create_rectangle(w, x, y, z)
def moveRectangle():
canvas.move(x, 10, 0)
# Run the moveRectangle function everytime the mainloop loops
window.mainloop()
To sum up my issue, I need to run mainloop as if it isn't a blocking function. Rather, either run it asynchronous, or maybe pause it and then run the function, though I don't think that's possible.
Anything helps Thanks
Upvotes: 0
Views: 1703
Reputation: 3824
I think there are ways to set up a custom mainloop()
which could update your UI every time the loop runs but depending on what you want to do the more usual method is to use after. By arranging for the function called by after to call itself with after an effective loop can be created.
I've amended you code to bounce the rectangle as it reaches the sides of the canvas so it can show something as it runs indefinitely.
import tkinter as tk
WAIT = 10 # in milliseconds, can be zero
window = tk.Tk()
window.geometry('%ix%i+400+0' % (500, 600))
canvas = tk.Canvas(window, width=500, height=600, bg='white')
canvas.pack()
w, x, y, z = 300, 300, 200, 200
x = canvas.create_rectangle(w, x, y, z)
amount = 10
def direction( current ):
x0, y0, x1, y1 = canvas.bbox( x )
if x0 <= 0:
return 10 # Move rect right
elif x1 >= 500:
return -10 # Move rect left
else:
return current
def moveRectangle():
global amount
canvas.move(x, amount, 0)
window.update()
# Change Direction as the rectangle hits the edge of the canvas.
amount = direction( amount )
window.after( WAIT, moveRectangle )
# ms , function
# Loop implemented by moveRectangle calling itself.
window.after( 1000, moveRectangle )
# Wait 1 second before starting to move the rectangle.
window.mainloop()
Upvotes: 1
Reputation: 195
Mainloop in tkinter doesn't loop through your code. It's looping through list of events. You can create an event by clicking buttons etc. Another way is that you can call commands like update()
or update_idletasks()
. Combinig that with after()
can give you results you are looking for. So look up these in documentation, it will be helpful. Also you can read: understanding mainloop.
def moveRectangle():
canvas.move(x, 10, 0)
for i in range(20): # 20 moves 10px every 50ms
window.after(50, canvas.move(x, 10, 0))
window.update()
moveRectangle()
This little code above demonstrate how you could use mentioned commands to get your object move on screen.
Upvotes: 3