You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Tkinter绘制箭头失败求助(含DFS实现代码)

DFS算法可视化中箭头无法显示的问题排查与修复

我在实现深度优先搜索(DFS)算法时,尝试用draw_arrow函数绘制节点间的箭头,但箭头始终无法显示。将draw_arrow移到window.mainloop()后也没能解决问题,以下是我的代码:

import random
import tkinter as tk

window = tk.Tk()
window.geometry("800x800")
canvas = tk.Canvas(window, width=800, height=800)
canvas.pack()


class Node:
    def __init__(self, number):
        self.number = number
        self.f = None
        self.d = None
        self.neighbor = []
        self.pi = None
        self.color = "white"
        self.y = random.randint(100, 700)
        self.x = random.randint(100, 700)


class Graph:
    def __init__(self):
        self.adjacency_list = []
        self.edges = {}
        self.lines = []
        self.arrows= []


def read_numbers(file_path):
    result = []
    with open(file_path, 'r') as file:
        for line in file:
            numbers = line.strip().split()
            if len(numbers) == 2:
                num_array = [int(numbers[0]), int(numbers[1])]
                result.append(num_array)
    return result


def create_adjacency_list(array):
    adj = []
    numbers = []
    nodes = []
    for pair in array:
        if pair[0] not in numbers:
            new_node1 = Node(pair[0])
            numbers.append(new_node1.number)
            adj.append(new_node1)
        if pair[1] not in numbers:
            new_node2 = Node(pair[1])
            numbers.append(new_node2.number)
            adj.append(new_node2)
    for pair in array:
        main = next((x for x in adj if x.number == pair[1]), None)
        secondary = next((x for x in adj if x.number == pair[1]), None)
        main.neighbor.append(secondary)
        draw_arrow(canvas,main,secondary)
    return adj


class Time():
    def __init__(self, value):
        self.value = value


def draw_circle(canvas, radius, node):
    x = node.x
    y = node.y
    canvas.create_oval(x - radius, y - radius, x + radius, y + radius, outline='black')
    canvas.create_text(x, y, text=str(node.number), fill='black', font=("Ariel",20))


def draw_arrow(canvas, start, end):
    return canvas.create_line(start.x, start.y, end.x, end.y, arrow=tk.LAST)


def create_circles(graph, canvas):
    numbers = []
    circles = []
    for i in graph.adjacency_list:
        if i.number not in numbers:
            numbers.append(i.number)
            circles.append(draw_circle(canvas, 30, i))
        for j in i.neighbor:
            if j.number not in numbers:
                numbers.append(j.number)
                circles.append(draw_circle(canvas, 30, j))
    return circles


def create_vertexes(graph):
    numbers = []
    vertexes = []
    for i in graph.adjacency_list:
        if i.number not in numbers:
            numbers.append(i.number)
            vertexes.append(i)
        for j in i.neighbor:
            if j.number not in numbers:
                numbers.append(j.number)
                vertexes.append(j)
    return vertexes

def DFS(start_node, time, vertexes):
    time.value = 0
    for u in vertexes:
        if u.color == "white":
            DFS_VISIT(u, time)


def DFS_VISIT(u, time):
    for i in u.neighbor:
        if i.color == "white":
            graph.edges[u, i]= 'tree'
        elif i.color == "gray":
            graph.edges[u, i] = "back"
        elif i.d < i.f:
            graph.edges[u, i] = "forward"
        else:
            graph.edges[u, i] = "cross"

    time.value = time.value + 1
    u.d = time.value
    u.color = "gray"
    for v in u.neighbor:
        if v.color == "white":
            v.pi = u
            DFS_VISIT(v, time)
    time.value = time.value + 1
    u.f = time.value
    u.color = "black"


time = Time(0)
graph = Graph()
numbers = read_numbers("./numbers.txt")
graph.adjacency_list = create_adjacency_list(numbers)
vertexes = create_vertexes(graph)
circles = create_circles(graph, canvas)

for i in graph.adjacency_list:
    for j in i.neighbor:
        graph.arrows.append(draw_arrow(canvas, i, j))
print(len(graph.adjacency_list))
window.mainloop()

问题根源与修复方案

  1. 邻接列表构建错误
    在create_adjacency_list函数中,错误地将main和secondary都指向了pair[1]对应的节点,导致每个节点的邻居是自身,箭头从节点指向自己,自然无法看到。正确写法应为:

    main = next((x for x in adj if x.number == pair[0]), None)
    secondary = next((x for x in adj if x.number == pair[1]), None)
    
  2. 冗余绘制导致箭头被覆盖
    create_adjacency_list中额外调用的draw_arrow会让箭头先于圆圈绘制,最终被圆圈覆盖,建议删除这一行冗余代码,只保留最后循环中的箭头绘制逻辑。

  3. 增加空值判断避免报错
    为防止节点查找失败出现空指针错误,可在添加邻居时增加非空判断:

    if main and secondary:
        main.neighbor.append(secondary)
    

修复后的create_adjacency_list函数:

def create_adjacency_list(array):
    adj = []
    numbers = []
    for pair in array:
        if pair[0] not in numbers:
            new_node1 = Node(pair[0])
            numbers.append(new_node1.number)
            adj.append(new_node1)
        if pair[1] not in numbers:
            new_node2 = Node(pair[1])
            numbers.append(new_node2.number)
            adj.append(new_node2)
    for pair in array:
        main = next((x for x in adj if x.number == pair[0]), None)
        secondary = next((x for x in adj if x.number == pair[1]), None)
        if main and secondary:
            main.neighbor.append(secondary)
    return adj

完成以上修改后,箭头即可正常显示在节点之间。

内容的提问来源于stack exchange,提问作者user17630065

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:43:18