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
#18
Okay, I have split my code into 4 files:

1. main function:
# SudokuSolver_main.py
import SudokuSolver_class as Sudokuolver
from tkinter import *


def main():
    root = Tk()
    app = Sudokuolver.SudokuSolver(root)
    root.mainloop()

if __name__ == '__main__':
    main()
2. Class with Userinterface
# SudokuSolver_class.py
import os
import SudokuSolver_solver as Solver
from random import randint
from tkinter import *
from tkcallasync import tk_call_async, MULTIPROCESSING


class SudokuSolver(Frame):

    disabled = False
    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)]
    exampleSudoku = [[' ',' ',' ','2','1',' ',' ',' ',' '],
                     [' ',' ','7','3',' ',' ',' ',' ',' '],
                     [' ','5','8',' ',' ',' ',' ',' ',' '],
                     ['4','3',' ',' ',' ',' ',' ',' ',' '],
                     ['2',' ',' ',' ',' ',' ',' ',' ','8'],
                     [' ',' ',' ',' ',' ',' ',' ','7','6'],
                     [' ',' ',' ',' ',' ',' ','2','5',' '],
                     [' ',' ',' ',' ',' ','7','3',' ',' '],
                     [' ',' ',' ',' ','9','8',' ',' ',' ']]

    def __init__(self, parent):
        Frame.__init__(self, parent, name='frame')
        self.parent = parent
        self.initUI()
        self.blankSUDOKU()

    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.execute_solver)
        self.solveBtn.grid(row=0,column=0)

        self.newBtn = Button(self, text="new",width=6,command=self.blankSUDOKU)
        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)

    # --- clear all fields and delete all values in sudoku[][] and solution[][] --- #
    def blankSUDOKU(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 a random Sudoku from textfiles ----- #
    def initSUDOKU(self):
        self.blankSUDOKU()
        self.message_txt.set('')
        L = len(os.listdir(os.getcwd() + "\sudokus")) / 2
        if L < 1:
            self.message_txt.set('No Sudokus saved, yet! Try this one')
            self.sudoku = self.copySUDOKU(self.exampleSudoku)
        else:
            # ----- fill sudoku array with values from textfile ----- #
            sudokuFile = open(os.getcwd() + "\sudokus\Sudoku%s.txt" % (randint(1, L)))
            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()
        # ----- make values from random sudoku appear in the GUI ----- #
        for row in range(9):
            for col in range(9):
                value = self.sudoku[row][col]
                if value!=' ':
                    self.values[row,col].insert(0,value)

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

    def saveSUDOKU(self):
       CHECK = self.checkSUDOKU(self.solution)
       if CHECK[0] and CHECK[1]:    # check if Sudoku is valid and complete
           filecount = 1    # variable for how many sudoku files are already existing
           while os.path.isfile(os.getcwd() + "\sudokus\sudoku%s.txt" % filecount):
               filecount += 1
           sudokuFile = open(os.getcwd() + "\sudokus\sudoku%s.txt" % filecount, 'w')
           solutionFile = open(os.getcwd() + "\sudokus\solution%s.txt" % filecount, 'w')
           # ----- create textfiles for sudoku and the solution ----- #
           for row in range(9):
               for col in range(9):
                   sudokuFile.write(self.sudoku[row][col])
                   solutionFile.write(self.solution[row][col])
               sudokuFile.write('\n')
               solutionFile.write('\n')
           sudokuFile.close()
           solutionFile.close()
           self.message_txt.set('Files saved...')
       else:
           self.message_txt.set('Sudoku must be valid and complete!')

    def copySUDOKU(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

    # ----- check if user input makes sense -----#
    def checkSUDOKU(self, matrix):
        valid, complete, ctr = True, True, 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
                        return valid, complete, row, col
                    matrix[row][col] = value
                    ctr += 1
                else: complete = False
        if ctr<17: valid = False
        return valid, complete

    # ----- 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]))

    # ----- 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

    # ----- 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

    def execute_solver(self):
        self.getinput(self.sudoku) # user input from GUI -> sudoku array
        if not self.checkSUDOKU(self.sudoku)[0]:    # check if user input makes sense
            self.message_txt.set("This sudoku does not have a solution")
        else:
            if self.disabled:
                self.message_txt.set("warning, It's still calculating...")
                return
        
            def callback(result):
                self.disabled
                self.disabled = False
                status, self.solution = result
                self.printSUDOKU(self.sudoku)
                self.printSUDOKU(self.solution)
                self.message_txt.set('Solution found!' if status else 'No Solution found!')
                self.fill_solution()

            self.disabled = True
            tk_call_async(self, Solver.do_solve, args=(self.sudoku,),
                      callback=callback, method=MULTIPROCESSING)

    def fill_solution(self):
        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])
3. the actual solving algorithm
# SudokuSolver_solver.py
def do_solve(sudoku):
    status = wsolve(sudoku)
    return status, sudoku

def consistent(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
 
class SolutionFound(Exception):
    pass
  
def wsolve(sudoku):
    try:
        solve(sudoku, 0)
    except SolutionFound:
        return True
    return False
 
def solve(sudoku, num):
    if num==81:
        raise SolutionFound
        return True
    else:
        row = int(num / 9)
        col = num % 9
        if sudoku[row][col]!=' ':
            solve(sudoku, num+1)
        else:
            for value in range(1,10):
                if consistent(sudoku, row, col, str(value)):
                    sudoku[row][col] = str(value)
                    if solve(sudoku, num+1): return True
                sudoku[row][col]=' '
            return False
  
if __name__ == '__main__':
    printSUDOKU(sudoku)
    solve(sudoku, 0)
4. tkcallasync.py - nothing changed on that code

I am very open to improvement suggestions.
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