Search code examples
pythonmultithreadingtkinter

Tkinter updating window while calculating otherthings


I am triying to write sudoku solver. This is really complicated code for me. I want to update board while python calculating other things. However, code could not do that. Should I try threading or is there easy way to do that?

CURRENT SITUATION: end of the calculation. I am inserting values. Then, I click solve. I am changing text of label (via code), but label waits untill end of calculations and suddenly applies labels' changes.

related codes in "def solve() > def set_text(), def check()"

my complete code:

import tkinter
from copy import deepcopy
import time
import threading

window = tkinter.Tk()
window.title("Sudoku Solver")
window.config(padx=30, pady=30)

zerolist = []  # adı posibles olacak
entrylist = []
exactvals = []
labellist = []

def create000():
    global zerolist
    global exactvals
    for i in range(9):
        zerolistemp = []
        exectemp = []
        for j in range(9):
            zerolistemp.append([])
            exectemp.append(0)
        zerolist.append(deepcopy(zerolistemp))
        exactvals.append(deepcopy(exectemp))
        zerolistemp.clear()
        exectemp.clear()
    return zerolist


# def solve():
#     def check(i,j):
#         global zerolist
#         for i in range(9):
#             for j in range(9):
#                 for element in zerolist[i][j]:
#                     if j == 9:


def solve():
    def set_text(x, y, text):
        time.sleep(1)
        global labellist
        if str(text) == "":
            labellist[x][y].config(text=str(text), background="gray")
        elif len(zerolist[x][y]) == 1:
            labellist[x][y].config(text=str(text), background="lightgreen")
        elif text != 0:
            labellist[x][y].config(text=str(text), background="red")
        return

    def check(i, j):
        print("check")
        global zerolist
        global exactvals
        columnpart = int(i / 3)
        rowpart = int(j / 3)
        for element in zerolist[i][j]:
            print(element)
            set_text(i, j, element)
            time.sleep(0.5)
            # elementi lable a yaz kırmızı yap
            # 3x3
            for m in range(3):
                for n in range(3):
                    if element == exactvals[columnpart + m][rowpart + n]:
                        zerolist[i][j].pop(element)
                        set_text(i, j, "")
                        return False

            if element in exactvals[i] or element in [row[j] for row in exactvals]:
                zerolist[i][j].pop(element)
                set_text(i, j, "")
                return False

            exactvals[i][j] = element
            if j != 8:
                if check(i, j + 1) == False:
                    exactvals[i][j] = 0
                    zerolist[i][j].pop(element)
                    set_text(i, j, "")
                    return False
            elif i != 8:
                if check(i + 1, 0) == False:
                    exactvals[i][j] = 0
                    zerolist[i][j].pop(element)
                    set_text(i, j, "")
                    return False
            else:
                # write yeşil
                set_text(i, j, element)
                return True

    check(0, 0)
    return exactvals


def collect_data():  # collec ederken zaten var  i j kullanıp uctan ekleyebiliriz
    global zerolist
    global exactvals
    global labellist
    for i in range(9):
        for j in range(9):  # yatay liste değiştiriyor
            if len(entrylist[i][j].get()) != 0:
                value = [int(entrylist[i][j].get())]
                exc = int(entrylist[i][j].get())
                labellist[i][j].config(text=exc, background="lightgreen")
            else:
                value = [x + 1 for x in range(9)]
                exc = 0
            zerolist[i][j] = value
            exactvals[i][j] = exc
    solve()
    return zerolist

for row in range(9):
    tempentry = []
    for column in range(9):
        a = tkinter.Entry(width=3)
        a.grid(column=column, row=row)
        tempentry.append(a)
    entrylist.append(tempentry)

emptylabel = tkinter.Label(width=3)
emptylabel.grid(column=9,row=0,rowspan=9)

for row in range(9):
    templabel = []
    for column in range(10, 19):
        a = tkinter.Label(width=3,borderwidth=2, relief="groove")
        a.grid(column=column, row=row)
        templabel.append(a)
    labellist.append(templabel)


but_solve = tkinter.Button(command=collect_data, text="SOLVE", width=9, pady=5)
but_solve.grid(columnspan=3, row=9, column=3)

create000()

window.mainloop()

I want to see changes in real-time while python calculating other things.

I tried threading like this: [![threading code][1]][1]

[1]: https://i.sstatic.net/ffyYu36t.png but tkinter does not give answer. ie stops.


Solution

  • Add a window.update() in your set_text function. This should update the tkinter window and show you the labels in real-time.