Search code examples
pythontkintervisualizationdelaysudoku

Is there a way to make this Python Tkinter function display numbers with some kind of delay effect?


I'm developing a simple Python GUI app to solve sudokus using Tkinter. My problem currently is that I've tried apparently all possible ways to add a little delay to the displaying of the solving numbers while the backtracking algorithm finds them, so as to get a visual effect on the grid (just like here).

Here is the code:

#F to solve puzzle
def solve_sudoku():
    find = find_empty()
    if not find_empty():
        return True
    else:
        x, y = find
    for num in range(1, 10):
        if validate_cell(x, y, num):
            sudoku[x][y].delete(0, "end")
            sudoku[x][y].insert(0, str(num))
            sudoku[x][y].config(fg = "SpringGreen3")
            #===> here goes the delay <===
            if solve_sudoku():
                return True
            sudoku[x][y].delete(0, "end")   
    return False

Now, .sleep() of course doesn't work because it affects the whole GUI. I've noticed that the only thing which seems to work somehow is the messagebox widget, but that's not the proper way to deal with it. I've tried also with other widgets, such as hiding some microlabel, but to no avail. What could possibly work?

EDIT1: tried as well with the .after() method but couldn't get anything good out of it.

EDIT2: sudoku[][] is a list of lists of Entry objects.

EDIT3: here you can find a quick very minimal reproducible example of the program.


Solution

  • All you have to do is call the function update_idletasks on the window when you are doing the sleep so that the widgets in the GUI are updated. Also you will have to declare window as a global variable since it is not in the function.

    import time
    def solve_sudoku():
        global window # Line added for wait
        find = find_empty()
        if not find_empty():
            return True
        else:
            x, y = find
        for num in range(1, 10):
            if validate_cell(x, y, num):
                sudoku[x][y].delete(0, "end")
                sudoku[x][y].insert(0, str(num))
                sudoku[x][y].config(fg = "SpringGreen3")
                time.sleep(0.01) # Line Added for wait
                window.update_idletasks() # Line Added for wait
                if solve_sudoku():
                    return True
                sudoku[x][y].delete(0, "end")   
        return False