Home > Enterprise >  Screen isn't updated in kivy
Screen isn't updated in kivy

Time:01-01

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.

  • Related