Tkinter отображается только в конце создания

#python #tkinter

Вопрос:

Довольно новичок в программировании с использованием Tkinter, и мне это дается с трудом. Я пытаюсь воссоздать это с помощью python и, по-видимому, наиболее подходящей библиотеки: Tkinter.

Как видно из видео, я хотел бы видеть, как мой код «работает», и хотел бы добавить немного сна к созданию лабиринта. В настоящее время я создал только сетку и функцию для ее раскрашивания. Хотя мне не удается раскрасить прямоугольники моего окна один за другим. Добавление режима сна заблокирует программу, и без этого все цвета будут отображаться все вместе.

Все решения, которые я видел, говорят о ярлыках с изменением текста, но я не могу заставить их работать на меня. Я что-то упускаю ?

Спасибо за вашу помощь !

 from tkinter import Tk, Canvas, Frame, BOTH
import random
from time import sleep

class Labyrinth(Frame):

    def __init__(self):
        super().__init__()
        self.master.title("Laby")
        self.pack(fill=BOTH, expand=1)

    def creat_grid(self, square_side, laby_side):
        grid = []
        canvas = Canvas(self, width = laby_side * square_side, height = laby_side * square_side)
        for y in range(laby_side):
            subgrid = []
            for x in range(laby_side):
                if ((y % 2 == 0 or y == laby_side - 1 or x % 2 == 0) and not (x == 0 and y == 1) and not (x == laby_side - 1 and y == laby_side - 2)):
                    subgrid.append(1)
                    canvas.create_rectangle(square_side * x, square_side * y, square_side * x   square_side, square_side * y   square_side, fill="black")
                else:
                    subgrid.append(0)
            grid.append(subgrid)

        canvas.pack(fill=BOTH, expand=1)
        return canvas, grid

def color_grid(root, canvas, grid, square_side):
    for y in range(len(grid)):
        for x in range(len(grid)):
            #sleep there blocks the program
            if (grid[y][x] == 0 and not (x == 0 and y == 1) and not (x == len(grid) - 1 and y == len(grid) - 2)):
                color = '#x' % random.randrange(16**3)
                while (color in grid):
                    color = '#x' % random.randrange(16**3)
                grid[y][x] = color
                canvas.create_rectangle(square_side * x, square_side * y, square_side * x   square_side, square_side * y   square_side, fill=color)
            #sleep there blocks the program
            root.update()
            #sleep there blocks the program
    canvas.pack(fill=BOTH, expand=1)

def main():
    root = Tk()
    laby = Labyrinth()

    square_side = 10
    laby_side = 51

    canvas, grid = laby.creat_grid(square_side, laby_side)
    color_grid(root, canvas, grid, square_side)
    root.mainloop()


if __name__ == '__main__':
    main()
 

Комментарии:

1. Дисплей не будет обновляться до тех пор, пока код не будет простаивать, чего не произойдет в циклах while (или в любом другом цикле). Реструктурируйте свою программу так, чтобы у вас была, например next_step() , функция, которая будет вызываться периодически или после каждого состояния простоя.

Ответ №1:

Вы можете использовать .after() для имитации эффекта бега. Также лучше один раз создать прямоугольники для заполнения, а затем обновить их цвета один за другим с помощью .after() :

 from tkinter import Tk, Canvas, Frame, BOTH
import random

class Labyrinth(Frame):

    def __init__(self):
        super().__init__()
        self.master.title("Laby")
        self.pack(fill=BOTH, expand=1)

    def create_grid(self, square_side, laby_side):
        grid = []
        canvas = Canvas(self, width=laby_side*square_side, height=laby_side*square_side, bg='black', highlightthickness=0)
        # create the to-be-filled rectangles
        for y in range(1, laby_side, 2):
            for x in range(1, laby_side, 2):
                x1, y1 = x*square_side, y*square_side
                grid.append(canvas.create_rectangle(x1, y1, x1 square_side, y1 square_side, fill='white'))
        canvas.pack()
        return canvas, grid

# create set of colors
colors = [f'#{x:03x}' for x in range(0x1000)]
# shuffle the colors in random order
random.shuffle(colors)

def color_grid(canvas, grid, i=0):
    canvas.itemconfig(grid[i], fill=colors[i])
    if i < len(grid)-1:
        # adjust the delay to suit your running effect
        canvas.after(5, color_grid, canvas, grid, i 1)

def main():
    root = Tk()
    laby = Labyrinth()

    square_side = 10
    laby_side = 51

    canvas, grid = laby.create_grid(square_side, laby_side)
    color_grid(canvas, grid)
    root.mainloop()


if __name__ == '__main__':
    main()