如何更新tkinter GUI的每一步?

2024-06-26 01:48:47 发布

您现在位置:Python中文网/ 问答频道 /正文

问题是,我做了一个简短的算法,找到它穿过迷宫的路径,并用蓝色标记它访问过的所有正方形。核心程序工作得很好,但问题是GUI只在整个过程完成后显示迷宫及其访问的方块。这通常不会是一个问题,但我需要能够明显地看到算法遍历迷宫,因为它去。问题是,当我在搜索算法的每次迭代中调用UpdateMaze函数时,它似乎直到整个遍历完成才生效。你知道吗

  • 墙上的图像只是一个黑色的正方形GIF
  • 空间图像只是一个白色的正方形GIF
  • 边缘图像只是一个红色的正方形GIF
  • 饰面为绿色正方形
  • 这是一个蓝色的正方形
import tkinter as tk
from tkinter import *
import time

class MazeGUI():
    def __init__(self):
        self.maze =[
            [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
            [4, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 4],
            [4, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 4],
            [4, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 4],
            [4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 4],
            [4, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 4],
            [4, 0, 1, 2, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 4],
            [4, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 4],
            [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
        ]
        self.wall = tk.PhotoImage(file = "MazePiece_Wall.gif")
        self.space = tk.PhotoImage(file = "MazePiece_Space.gif")
        self.edge = tk.PhotoImage(file = "MazePiece_Outer.gif")
        self.visited = tk.PhotoImage(file = "MazePiece_Visited.gif")
        self.finish = tk.PhotoImage(file = "MazePiece_Finish.gif")

    def UpdateMaze(self):
        for y in range(len(self.maze)):
            for x in range(len(self.maze[y])):
                if self.maze[y][x] == 0:
                    label = Label(root, image=self.space,
                                  width=20, height=20).grid(row=y, column=x)
                elif self.maze[y][x] == 1:
                    label = Label(root, image=self.wall,
                                  width=20, height=20).grid(row=y, column=x)
                elif self.maze[y][x] == 2:
                    label = Label(root, image=self.finish,
                                  width=20, height=20).grid(row=y, column=x)
                elif self.maze[y][x] == 3:
                    label = Label(root, image=self.visited,
                                  width=20, height=20).grid(row=y, column=x)
                elif self.maze[y][x] == 4:
                    label = Label(root, image=self.edge,
                                  width=20, height=20).grid(row=y, column=x)


def Move(Maze,x,y):
    if Maze.maze[y][x] == 2:
        return True
    elif Maze.maze[y][x] == 1:
        return False
    elif Maze.maze[y][x] == 3:
        return False
    elif Maze.maze[y][x] == 4:
        return False
    Maze.maze[y][x] = 3
    if ((x < len(Maze.maze)-1 and Move(Maze,x+1, y))
        or (y > 0 and Move(Maze,x, y-1))
        or (x > 0 and Move(Maze,x-1, y))
        or (y < len(Maze.maze)-1 and Move(Maze,x, y+1))):
        return True
    return False

root = Tk()
Maze = MazeGUI()
root.lift()
StartPosX = 1
StartPosY = 1
Move(Maze,StartPosX,StartPosY)
Maze.UpdateMaze()
root.mainloop()

Tags: selfmovereturnrootgiflabeltkfile
1条回答
网友
1楼 · 发布于 2024-06-26 01:48:47

我认为下面的内容展示了如何做你想做的事情的基本知识。它使用tkinter通用^{}方法定期调用make_move()方法,该方法最终调用update_maze()来重新显示每次移动后的迷宫。你知道吗

看起来好像什么都没有发生,但过一段时间你应该会看到迷宫显示的变化。由于使用了我介绍的random模块来生成下一步应该是什么,所以具体需要多长时间是不可预测的——因为我真的不理解在示例代码的Move()函数中这样做的逻辑。这是什么可能需要“修复”它,确切地说,无论它是你试图完成。你知道吗

注意:我还更改了您的代码,使其在代码格式和类、函数、变量等的命名方面更接近PEP 8 - Style Guide for Python Code,以使其更具可读性(IMO)。你知道吗

from random import randint
import tkinter as tk
from tkinter import *
import time

MOVE_DELAY = 1000  # Time delay between moves in millisec.

class MazeGUI():
    SPACE = 0
    WALL = 1
    FINISH = 2
    VISITED = 3
    EDGE = 4

    def __init__(self):
        self.maze = [
            [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
            [4, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 4],
            [4, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 4],
            [4, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 4],
            [4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 4],
            [4, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 4],
            [4, 0, 1, 2, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 4],
            [4, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 4],
            [4, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 4],
            [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
        ]
        self.wall = tk.PhotoImage(file="MazePiece_Wall.gif")        # black
        self.space = tk.PhotoImage(file="MazePiece_Space.gif")      # white
        self.edge = tk.PhotoImage(file="MazePiece_Outer.gif")       # red
        self.finish = tk.PhotoImage(file="MazePiece_Finish.gif")    # green
        self.visited = tk.PhotoImage(file="MazePiece_Visited.gif")  # blue
        self.create_maze()

    def create_maze(self):
        global root

        self.maze_frame = tk.Frame(root)
        self.create_maze_labels()
        self.maze_frame.pack()

    def update_maze(self):
        global root

        self.maze_frame.grid_forget()  # Remove all the existing Labels.
        self.create_maze_labels()
        self.maze_frame.update_idletasks()  # Update display.

    def create_maze_labels(self):
        for y in range(len(self.maze)):
            for x in range(len(self.maze[y])):
                if self.maze[y][x] == self.SPACE:
                    Label(self.maze_frame, image=self.space,
                          width=20, height=20).grid(row=y, column=x)
                elif self.maze[y][x] == self.WALL:
                    Label(self.maze_frame, image=self.wall,
                          width=20, height=20).grid(row=y, column=x)
                elif self.maze[y][x] == self.FINISH:
                    Label(self.maze_frame, image=self.finish,
                          width=20, height=20).grid(row=y, column=x)
                elif self.maze[y][x] == self.VISITED:
                    Label(self.maze_frame, image=self.visited,
                          width=20, height=20).grid(row=y, column=x)
                elif self.maze[y][x] == self.EDGE:
                    Label(self.maze_frame, image=self.edge,
                          width=20, height=20).grid(row=y, column=x)

    def make_move(self, x, y):
        global root

        status = self.move(x, y)
        # if status:  # Not sure what to do with return value...
        self.update_maze()

        # Select a random adjoining cell (dx & dy both +/-1).
        dx, dy = randint(0, 2) - 1, randint(0, 2) - 1
        x, y = x+dx, y+dy  # Next position.
        root.after(MOVE_DELAY, self.make_move, x, y)  # Repeat...

    def move(self, x, y):
        if self.maze[y][x] == self.FINISH:
            return True
        elif self.maze[y][x] == self.WALL:
            return False
        elif self.maze[y][x] == self.VISITED:
            return False
        elif self.maze[y][x] == self.EDGE:
            return False

        # Spot is empty (self.SPACE).
        self.maze[y][x] = self.VISITED

        if ((x < len(self.maze)-1 and self.move(x+1, y))
             or (y > 0 and self.move(x, y-1))
             or (x > 0 and self.move(x-1, y))
             or (y < len(self.maze)-1 and self.move(x, y+1))):
            return True
        return False

root = Tk()
maze = MazeGUI()

start_posx, start_posy = 1, 1
maze.make_move(start_posx, start_posy)
maze.update_maze()
root.mainloop()

对任何感兴趣的人来说,这里是我制作并用于测试的.gif图像(因此您可以下载它们来运行代码):

  • MazePiece_Finish.gifMazePiece_Finish.gif
  • MazePiece_Outer.gifMazePiece_Outer.gif
  • MazePiece_Space.gifMazePiece_Space.gif
  • MazePiece_Visited.gifMazePiece_Visited.gif
  • MazePiece_Wall.gifMazePiece_Wall.gif

相关问题 更多 >