Search code examples
pythonpython-3.xtkinterconways-game-of-life

Running a function multiple time and displaying output on tkinter


I am coding 'The Game Of Life' and using tkinter as a GUI. I have a grid (just a grid of 20 by 20 Buttons), and and an 'updateGrid' function that takes the current values of the grid and updates it according to the rules of The Game Of Life. I linked the 'updateGrid' function to a 'Next' button, thus if the Next button is clicked, the grid is updated. I want to implement a 'runGrid' function, (connected to a 'Run' button) that runs the 'updateGrid' function numerous times. I've tried this:

def runGrid():
    for i in range(0, 10):
        updateGrid()
        time.sleep(4)

but it seems like the tkinter GUI only updates once the runGrid function is completed. I want the tkinter GUI to update after each iteration so that the user can see the progress of the runGrid function.

Here is a screenshot of the grid before any button is pressed: enter image description here

Here is a screenshot of the grid after the 'runGrid' function is executed: enter image description here

The glider (the pattern) 'moves' from the first position to the last position in 10 moves, however, only the first and the last position is can be seen with the runGrid function. If the updateGrid function is called 10 times in a row, every move can be seen.


Solution

  • When GUIs (tkitner, PyQt, other GUIs, other languages) run your function then they does't update widgets at once but they wait for end of your code and they update all widgets only once. This way they have less work and they redraw window only once so it doesn't blink.


    You can use after(milliseconds, function_name, [arg1, ...]) to execute function periodically without blocking mainloop

    Something like this

    def runGrid(i=10):
        updateGrid()
        if i > 0:
           root.after(4000, runGrid, i-1)  # 4000ms = 4s
    

    Eventually you can use root.update() to force mainloop to redraw window

    def runGrid():
        for i in range(0, 10):
            updateGrid()
            root.update()
            time.sleep(4)