【问题标题】:Use tkinter to visualize A Star search algorithm使用 tkinter 可视化 A 星搜索算法
【发布时间】:2015-08-31 04:22:23
【问题描述】:

我编写了一个 A* 搜索算法,并希望使用 tkinter 以图形方式可视化搜索(实时),如下图所示,只是一个更简单的版本,没有菜单、单元格中的数字、以前尝试过的路径或对角线路径.

换句话说,我只需要显示一个网格,其中包含 7 种可能的纹理(开始、结束、路径、障碍物、开放节点、封闭节点、未尝试),当底层矩阵更改时会自动更新。

可以说,这个外观的轮廓或架构如何?我已经有一个 2x2 矩阵,其中包含每个节点状态的值(开始.. 障碍等),如何在每次更改时使用 tkinter 显示该矩阵?

到目前为止,我得到了这个:

def main():
    theMap = .. # initial map with start, finish and obstacles
    root = Tk()
    my_gui = CellGrid(root,n,m,40,theMap)
    root.mainloop()
class CellGrid(Canvas):
    def __init__(self,master, rowNumber, columnNumber, cellSize, theMap):
        Canvas.__init__(self, master, width = cellSize * columnNumber , height = cellSize * rowNumber)

        self.cellSize = cellSize

        self.grid = []
        for row in range(rowNumber):
            line = []
            for column in range(columnNumber):
                line.append(Cell(self, column, row, cellSize, theMap[row][column]))
            self.grid.append(line)

        print self.grid[0][0].value
        self.draw()


    def draw(self):
        for row in self.grid:
            for cell in row:
                cell.draw()

class Cell():
    START_COLOR = "green"
    FINISH_COLOR = "red"
    UNTRIED_COLOR = "white"
    CLOSED_COLOR = "gray"
    OPEN_COLOR = "blue"
    OBSTACLE_COLOR = "black"
    PATH_COLOR = "orange"

    def __init__(self, master, x, y, size, value):
        self.master = master
        self.abs = x
        self.ord = y
        self.size= size
        self.fill = "white"
        self.value = value

    def setValue(self, value):
        self.value = value

    def draw(self):
        """ order to the cell to draw its representation on the canvas """
        if self.master != None :
            if self.value == 0:
                self.fill = self.UNTRIED_COLOR
            elif self.value == 1:
                self.fill = self.OBSTACLE_COLOR
            elif self.value == 2:
                self.fill = self.START_COLOR
            elif self.value == 3:
                self.fill = self.FINISH_COLOR
            elif self.value == 4:
                self.fill = self.OPEN_COLOR
            elif self.value == 5:
                self.fill = self.CLOSED_COLOR
            elif self.value == 6:
                self.fill = self.PATH_COLOR

            xmin = self.abs * self.size
            xmax = xmin + self.size
            ymin = self.ord * self.size
            ymax = ymin + self.size

            self.master.create_rectangle(xmin, ymin, xmax, ymax, fill = self.fill, outline = "black")

这个想法是绘制仅包含开始、结束和障碍节点的初始地图(theMap)。然后,当 A* 更改节点时,它可以调用 CellGrid 中的一个方法,为该节点提供一个新值,然后更新该值并绘制相应的纹理。

但是我无法做到这一点。当我运行上面的代码时,我什么也得不到,只是一个空的 Tk 窗口。它有什么问题?

【问题讨论】:

    标签: python tkinter a-star


    【解决方案1】:

    发布的代码没有运行。它确实(在 3.x 中),例如,当它以

    开头时
    from tkinter import *
    
    def main():
        Map = [
                [2, 0, 0, 0, 0],
                [0, 1, 1, 1, 1],
                [0, 1, 3, 0, 0],
                [0, 1, 1, 1, 0],
                [0, 0, 0, 0, 0],
              ]
        root = Tk()
        my_gui = CellGrid(root, len(Map), len(Map[0]), 40, Map)
        root.mainloop()
    

    和括号被添加到打印语句中。

        print(self.grid[0][0].value)  # harmless in 2.7
    

    并以main() 结尾。使用简单的数据对开发很有帮助。

    要回答您的直接问题,使画布可见需要在 Canvas 初始化后添加 self.pack。这样,上面的地图就按预期显示了。

    为了回答您的架构问题,我建议采用不同的方法。定义一个自定义 Map 类,该类包含您当前称为 theMap 的列表列表、Canvas 以及采用索引元组的 getitemsetitem 方法。用 amap[(i,j)] 写出你的 A* 函数。 setitem 方法将负责设置数组和画布。

    Python风格说明:上面所有颜色代码都可以替换为

    colors = {
                0: 'white',    # untried
                1: 'black',    # obstacle
                2: 'green',    # start
                3: 'red',      # finish
                4: 'blue',     # open
                5: 'gray',     # closed
                6: 'orange',   # path
             }
    

    在 create_rectangle 调用中跟在 fill=colors[self.value] 之后。

    【讨论】:

    • 优秀的答案。缺少 self.pack 以启动和运行画布。但现在我面临一个不同的问题。要么我必须在单独的线程中运行 A-Star 和 Tkinter。如果是这样,我如何在 A-star 运行时更新 Tkinter 地图?选项 2 是只运行一个线程,并让 A-Star 调用一个函数,该函数每次进行更改时都会更新 GUI,但我认为后者是不可能的,是吗?
    • 你为什么不这么认为?我看到的问题是全速 A* 运行速度太快,因此您需要放慢速度。例如,编写一个函数astep,它执行一个搜索“步骤”,根据需要使用a_map[(m,n)] = colorcode 语句重新着色地图。然后在astep 的末尾和root.mainloop 之前添加root.after(delay, astep),其中延迟可能是50(毫秒)。例如,请参阅我对stackoverflow.com/questions/32296814/… 的回答。
    • 好的。我在每个单独的线程中制作了 Tkinter 和 A-Star,A-star 更新地图并在每次更改时调用 GUI 来更新渲染。因为我需要显示当前正在探索的路径,所以每次 A-Star 进行更改时都需要更新整个地图。但这会使整个程序非常缓慢;如果没有 Tkinter,我可以在一秒钟内完成 10 个“场景”,而一个“场景”需要 20 秒,这意味着慢 200 倍(给你一个印象)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2011-08-16
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    相关资源
    最近更新 更多