简体   繁体   中英

Using Python and Tkinter, How would I run code every loop of .mainloop()?

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

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.

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM