So this is simple sudoku solver with backtracking (using recursion). It's made so after every recursion the screen updates (to show a change), but it doesn't display anything until it's completely done. Where's the problem? Also maybe there is better way to update screen after each change?
The code:
'''
def update_numbers(self):
self.clear_widgets()
greeting = Label(text="Sudoku", pos=(self.width/2 - 70, 1200), size_hint=(0.2, 0.08))
self.add_widget(greeting)
v_x, v_y = 15, 955
for k, row in enumerate(board, start=1):
for k1, col in enumerate(row, start=1):
self.add_widget(Label(text=str(col), pos=(v_x, v_y), size_hint=(0.3, 0.3)))
v_x = 60
v_x = 15
v_y -= 60
def solve(self, bo):
self.update_numbers() # should update the screen
#everything further is solver itself
find = find_empty(bo)
if find:
row, col = find
else:
return True
for i in range(1, 10):
if valid(bo, (row, col), i):
bo[row][col] = i
if self.solve(bo):
return True
bo[row][col] = 0
return False
'''
Edit: After looking at similar problem here: How do I update Kivy elements from a thread?
I found a solution to this problem: '''
def display_setup(self):
greeting = Label(text="Sudoku", pos=(self.width/2 - 70, 1200), size_hint=(0.2, 0.08))
self.add_widget(greeting)
v_x, v_y = 15, 955
for k, row in enumerate(board, start=1):
for k1, col in enumerate(row, start=1):
the_label = Label(text=str(col), pos=(v_x, v_y), size_hint=(0.3, 0.3))
self.labels.append(the_label)
self.add_widget(the_label)
v_x = 60
v_x = 15
v_y -= 60
@mainthread
def update_numbers(self, *dt):
for k, label in enumerate(self.labels):
row = k // 9
label.text = str(board[row][k % 9])
def solve(self, bo):
Clock.schedule_once(self.update_numbers, 0)
time.sleep(0.05)
.....
CodePudding user response:
If you are running solve()
on the main thread (as it would be if it is triggered by a Button), then the display cannot be updated until the solve()
method returns. The display can only be updated on the main thread, and only when the main thread is available.
The fix is to start the solve()
process in another thread (see threading), then mark the update_numbers()
method as a mainthread
method:
@mainthread
def update_numbers(self):
That causes the update_numbers()
method to be run on the main thread.