Python Forum
[Tkinter] tkinter freezes by clicking button
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] tkinter freezes by clicking button
#8
Hi, thanks for your help. Unfortunately the code doesnt seem to work on windows. When I press "Solve Sudoku" another instance of tkinter shows up. By pressing it again he says that its still calculating but even after waiting for 10 minutes there is no solution printed in python shell.

[Image: stillrunningwkrcp.jpg]

@woooee
I am using tkinter but I left out that part of the code because it is a lot and quite messy. Here is the whole code if you are interested:
import time
import os
from random import randint
from tkinter import *


class SudokuSolver(Frame):

    backtrack_ctr = 0
    sudoku = [[" " for col in range(9)] for row in range(9)]
    solution = [[" " for col in range(9)] for row in range(9)]

    def __init__(self, parent):

        Frame.__init__(self, parent, name='frame')
        self.parent = parent
        self.initUI()
        self.newSUDOKU()


    def initUI(self):

        self.message_txt = StringVar()
        self.values = {}

        self.parent.title('Sudoku Solver')
        self.pack(fill=BOTH, expand=True)

        self.message = Label(self, textvariable=self.message_txt)
        self.message.grid(row=10,column=0,columnspan=8, sticky=E+W)

        self.solveBtn = Button(self, text="solve",width=6,command=self.solveSUDOKU)
        self.solveBtn.grid(row=0,column=0)

        self.newBtn = Button(self, text="new",width=6,command=self.newSUDOKU)
        self.newBtn.grid(row=0,column=1)

        self.initBtn = Button(self, text="init",width=6,command=self.initSUDOKU)
        self.initBtn.grid(row=0,column=2)

        self.printBtn = Button(self, text="print",width=6,command=self.printSUDOKU)
        self.printBtn.grid(row=0,column=8)

        self.checkBtn = Button(self, text="check",width=6,command=self.checkSOLUTION)
        self.checkBtn.grid(row=0,column=6)

        self.saveBtn = Button(self, text="save",width=6,command=self.saveSUDOKU)
        self.saveBtn.grid(row=0,column=7)


    # ----- make all fields empty ----- #
    def newSUDOKU(self):

        self.message_txt.set('')
        for row in range(9):
            for col in range(9):
                self.sudoku[row][col] = ' '
                self.solution[row][col] = ' '
                self.numEntry = Entry(self, width=5, justify=CENTER,
                                 font="Helvetica 12 bold")
                self.values[row,col] = self.numEntry
                self.numEntry.grid(row=row+1,column=col, ipady=5)


    # ----- get random Sudoku from textfiles ----- #
    def initSUDOKU(self):

        self.newSUDOKU()
        self.message_txt.set('')
        L = len(os.listdir(os.getcwd() + "\sudokus")) / 2
        sudokuFile = open(os.getcwd() + "\sudokus\Sudoku%s.txt" % (randint(1, L)))

        # ----- fill sudoku_original array with values from textfile ----- #
        row, col = 0, 0
        for value in sudokuFile.read():
            if value.isdigit() or value==' ':
                self.sudoku[row][col]=value
                col += 1
                if col==9:
                    if row==8: break
                    row += 1
                    col = 0

        sudokuFile.close()
        self.sudoku_original = self.copy(self.sudoku)

        for row in range(9):
            for col in range(9):
                value = self.sudoku[row][col]
                if value!=' ':
                    self.values[row,col].insert(0,value)


    # ----- write user input into values{} ----- #

    def getinput(self, matrix):

        for row in range(9):
            for col in range(9):
                value = self.values[row,col].get()
                if value=='': matrix[row][col] = ' '
                elif len(value)!=1: matrix[row][col] = ' '
                elif not value.isdigit(): matrix[row][col] = ' '
                elif int(value)<1 or int(value)>9: matrix[row][col] = ' '
                else : matrix[row][col] = value


    # ----- print matrix ----- #

    def printMATRIX(self, matrix):

        for row in range(9):
            print("|-----------------------------------|")
            for col in range(9):
                print("| " + matrix[row][col] + " ",end='')
            print("|")
        print("|-----------------------------------|")


    # ----- save sudoku ----- #

    def saveSUDOKU(self):

       CHECK = self.checkSUDOKU(self.solution)
       if CHECK[0] and CHECK[1]:
           num = 1
           while os.path.isfile(os.getcwd() + "\sudokus\sudoku%s.txt" % num): num += 1
           sudokuFile = open(os.getcwd() + "\sudokus\sudoku%s.txt" %num, 'w')
           solutionFile = open(os.getcwd() + "\sudokus\solution%s.txt" %num, 'w')

           for row in range(9):
               for col in range(9):
                   sudokuFile.write(self.sudoku_original[row][col])
                   solutionFile.write(self.solution[row][col])
               sudokuFile.write('\n')
               solutionFile.write('\n')
           sudokuFile.close()
           solutionFile.close()
           print("FILES SAVED!")
           self.message_txt.set("Files saved...")



    # ----- print sudoku_original, sudoku, solution ----- #

    def printSUDOKU(self):

        print("Original : ")
        self.printMATRIX(self.sudoku_original)
        print("Sudoku : ")
        self.printMATRIX(self.sudoku)
        print("Solution : ")
        self.printMATRIX(self.solution)
        if  not self.checkSUDOKU(self.sudoku)[0]:
            print("sudoku is not valid")



    # ----- check if this input leads to a valid solution ----- #

    def consistent(self, matrix, row, col, value):

        for i in range(9):
            if matrix[row][i]==value: return False
            if matrix[i][col]==value: return False
        rowStart = row - row%3
        colStart = col - col%3
        for m in range(3):
            for k in range(3):
                if matrix[rowStart+k][colStart+m]==value: return False
        return True


    # ----- check if user input makes sense -----#

    def checkSUDOKU(self, matrix):
        valid, complete, rowM, colM, ctr = True, True, 0, 0, 0
        for row in range(9):
            for col in range(9):
                value = matrix[row][col]
                if value!=' ':
                    matrix[row][col]=' '
                    if not self.consistent(matrix,row,col,value):
                        valid, complete = False, True
                        rowM, colM = row+1, col+1
                        print("MISTAKE AT row=%s ,col=%s" % (row+1, col+1))
                        return valid, complete, rowM, colM
                    matrix[row][col] = value
                    ctr += 1
                else: complete = False
        if ctr<17: valid = False
        return valid, complete, rowM, colM



    # ----- check if solution is valid ----- #

    def checkSOLUTION(self):

        self.getinput(self.sudoku)
        CHECK = self.checkSUDOKU(self.sudoku)
        if CHECK[0] and CHECK[1]: self.message_txt.set("Solution correct!")
        elif not CHECK[1]: self.message_txt.set("Sudoku is not complete!")
        elif not CHECK[0]: self.message_txt.set("Mistake at row %s, col %s"
                                      % (CHECK[2], CHECK[3]))



    # ----- returns an exact copy of 2dim array ----- #

    def copy(self, matrix):

        matrix_copy = [[" " for col in range(9)] for row in range(9)]
        for row in range(9):
            for col in range(9):
                matrix_copy[row][col] = matrix[row][col]
        return matrix_copy



    # ----- solve current sudoku ----- #

    def solveSUDOKU(self):

        self.getinput(self.sudoku)  # get user input from GUI and write it into sudoku arrey
        if not self.checkSUDOKU(self.sudoku)[0]:    # check if user input makes sense
            self.message_txt.set("This sudoku does not have a solution")
        # ----- save time how long the solving took ----- #
        else:
            start = time.time()
            solve(0)    # start backtracking
            end = time.time()
            self.message_txt.set("%s seconds, %s backtracks"%(round((end-start),3)
                                                              ,self.backtrack_ctr))
            self.backtrack_ctr = 0      # reset backtrack counter

            # ----- fill all fields with the solution ----- #
            for row in range(9):
                for col in range(9):
                    self.values[row,col].delete(0,END)
                    self.values[row,col].insert(0,self.solution[row][col])




# ----- backtracking algorithm ----- #

def solve(num):
    SudokuSolver.backtrack_ctr += 1
    if num==81:
        print("Solution found!")
        SudokuSolver.solution = SudokuSolver.copy(SudokuSolver,SudokuSolver.sudoku)
        return True
    else:
        row = int(num / 9)
        col = num % 9
        if SudokuSolver.sudoku[row][col]!=' ':
            solve(num+1)
        else:
            for value in range(1,10):
                if SudokuSolver.consistent(SudokuSolver,SudokuSolver.sudoku,
                                           row,col,str(value)):
                    SudokuSolver.sudoku[row][col]=str(value)
                    if solve(num+1): return True
                SudokuSolver.sudoku[row][col]=' '
            return False



def main():

    root = Tk()
    app = SudokuSolver(root)
    root.mainloop()

if __name__== '__main__':
    main()
if you want the init function to work you have to create a folder called "sudokus" and save it to your working directory. Within that folder you create a .txt file called "sudoku1.txt" with the following content:
   21    
  73     
 58      
43       
2       8
       76
      25 
     73  
    98   
all spaces needed

I have not tried using after() method, yet but I suspect that it would slow down the program substantially because it is called in every backtracking step. For example if there are 10k backtracks needed for a certain sudoku, the program would need 1000s longer than normal and 10k backtracks are not even a lot.
Reply


Messages In This Thread
tkinter freezes by clicking button - by Zatox11 - Mar-30-2018, 11:38 AM
RE: tkinter freezes by clicking button - by Zatox11 - Mar-30-2018, 02:31 PM
RE: tkinter freezes by clicking button - by Zatox11 - Mar-30-2018, 03:32 PM
RE: tkinter freezes by clicking button - by woooee - Mar-30-2018, 07:35 PM
RE: tkinter freezes by clicking button - by Zatox11 - Mar-31-2018, 08:46 AM
RE: tkinter freezes by clicking button - by Zatox11 - Mar-31-2018, 09:18 AM
RE: tkinter freezes by clicking button - by Zatox11 - Mar-31-2018, 10:23 AM
RE: tkinter freezes by clicking button - by Zatox11 - Mar-31-2018, 10:48 AM
RE: tkinter freezes by clicking button - by Zatox11 - Mar-31-2018, 02:15 PM
RE: tkinter freezes by clicking button - by Zatox11 - Apr-01-2018, 11:38 AM
RE: tkinter freezes by clicking button - by Zatox11 - Apr-02-2018, 12:58 PM
RE: tkinter freezes by clicking button - by Zatox11 - Apr-02-2018, 04:07 PM
RE: tkinter freezes by clicking button - by Zatox11 - Apr-03-2018, 10:50 AM
RE: tkinter freezes by clicking button - by Zatox11 - Apr-03-2018, 02:58 PM
RE: tkinter freezes by clicking button - by sylas - Apr-06-2018, 07:57 AM
RE: tkinter freezes by clicking button - by sylas - Apr-06-2018, 09:10 AM
RE: tkinter freezes by clicking button - by sylas - Apr-08-2018, 09:32 AM
RE: tkinter freezes by clicking button - by sylas - Apr-08-2018, 12:01 PM
RE: tkinter freezes by clicking button - by sylas - Apr-08-2018, 01:05 PM
RE: tkinter freezes by clicking button - by sylas - Apr-08-2018, 03:28 PM
RE: tkinter freezes by clicking button - by Zatox11 - Apr-10-2018, 09:03 AM

Possibly Related Threads…
Thread Author Replies Views Last Post
  [Tkinter] TKinter Remove Button Frame Nu2Python 8 1,537 Jan-16-2024, 06:44 PM
Last Post: rob101
  tkinter - touchscreen, push the button like click the mouse John64 5 1,169 Jan-06-2024, 03:45 PM
Last Post: deanhystad
  Centering and adding a push button to a grid window, TKinter Edward_ 15 6,194 May-25-2023, 07:37 PM
Last Post: deanhystad
  [Tkinter] Clicking on the button crashes the TK window ODOshmockenberg 1 2,379 Mar-10-2022, 05:18 PM
Last Post: deanhystad
  Can't get tkinter button to change color based on changes in data dford 4 3,648 Feb-13-2022, 01:57 PM
Last Post: dford
  Creating a function interrupt button tkinter AnotherSam 2 5,817 Oct-07-2021, 02:56 PM
Last Post: AnotherSam
  [Tkinter] Have tkinter button toggle on and off a continuously running function AnotherSam 5 5,353 Oct-01-2021, 05:00 PM
Last Post: Yoriz
  tkinter showing image in button rwahdan 3 5,895 Jun-16-2021, 06:08 AM
Last Post: Yoriz
  tkinter button image Nick_tkinter 4 4,282 Mar-04-2021, 11:33 PM
Last Post: deanhystad
  tkinter python button position problem Nick_tkinter 3 3,760 Jan-31-2021, 05:15 AM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020