在Tkinter中如何将坐标追加到列表且避免被覆盖
视力测试APP坐标记录问题修复
问题描述
正在开发一款视力测试APP:用户注视屏幕中心注视点,每隔几秒出现并消失刺激物,测试持续1分钟。当刺激物显示时用户按下空格键,需记录该刺激物的坐标并追加到列表,最终根据按键情况展示用户视野范围。
当前问题:坐标追加到列表时不断被覆盖,仅能保留最后一个坐标。经排查,问题出在get_results()函数——每次调用该函数都会初始化self.accuracies为空列表,导致之前的记录被清空。
问题代码片段
def get_results(self, event): self.accuracies = [] inaccuracies = [] if len(self.canvas.coords(self.dot)) > 0: self.accuracies.append(self.canvas.coords(self.dot)) print(self.accuracies) def test_results_page(self): print(self.accuracies) self.destroy_widgets() canvas = Canvas(self.root, bg="white") canvas.place(relx=0, rely=0, relwidth=1, relheight=1) canvas.create_rectangle(self.accuracies[0][0], self.accuracies[0][1], self.accuracies[0][2], self.accuracies[0][3], outline="black", fill="black") def draw_dot(self, x, y, color): self.dot = self.canvas.create_oval(x, y, x + 10, y + 10, outline=color, fill=color) self.root.bind("<space>", self.get_results)
修复方案
- 移除
get_results()内的列表初始化
删除self.accuracies = []这行代码,避免每次触发空格键都清空记录列表。 - 在类初始化方法中初始化
self.accuracies
确保列表仅在APP实例创建时初始化一次,示例:def __init__(self, root): self.root = root self.accuracies = [] # 仅初始化一次空列表 # 其他初始化代码(如创建画布、设置注视点等) - 修复结果页的坐标绘制逻辑
当前代码仅绘制第一个记录的坐标,需遍历所有记录的坐标来完整展示视野范围:def test_results_page(self): print(self.accuracies) self.destroy_widgets() canvas = Canvas(self.root, bg="white") canvas.place(relx=0, rely=0, relwidth=1, relheight=1) # 遍历所有记录的坐标进行绘制 for coords in self.accuracies: canvas.create_rectangle(coords[0], coords[1], coords[2], coords[3], outline="black", fill="black") - 优化按键绑定逻辑
避免每次绘制刺激物都重复绑定空格键,将绑定操作移至类初始化方法中,防止多次绑定导致重复触发:def __init__(self, root): self.root = root self.accuracies = [] self.root.bind("<space>", self.get_results) # 仅绑定一次空格键 # 其他初始化代码 - 可选:添加坐标副本存储
由于canvas.coords()返回的是引用,后续刺激物坐标变化可能影响已记录的列表,建议存储坐标的副本:self.accuracies.append(self.canvas.coords(self.dot).copy())
修正后的完整关键代码
class VisionTestApp: def __init__(self, root): self.root = root self.accuracies = [] # 初始化空记录列表 self.root.bind("<space>", self.get_results) # 单次绑定空格键 # 初始化主画布 self.canvas = Canvas(self.root, bg="white") self.canvas.place(relx=0, rely=0, relwidth=1, relheight=1) # 绘制中心注视点(示例) self.canvas.create_oval(490, 290, 510, 310, outline="red", fill="red") def get_results(self, event): # 移除清空列表的代码 inaccuracies = [] # 若未使用可删除 if len(self.canvas.coords(self.dot)) > 0: # 存储坐标副本,避免后续修改影响记录 self.accuracies.append(self.canvas.coords(self.dot).copy()) print(self.accuracies) def test_results_page(self): print(self.accuracies) self.destroy_widgets() canvas = Canvas(self.root, bg="white") canvas.place(relx=0, rely=0, relwidth=1, relheight=1) # 绘制所有记录的刺激物坐标 for coords in self.accuracies: canvas.create_rectangle(coords[0], coords[1], coords[2], coords[3], outline="black", fill="black") def draw_dot(self, x, y, color): self.dot = self.canvas.create_oval(x, y, x + 10, y + 10, outline=color, fill="black") # 移除重复的空格键绑定代码
内容的提问来源于Stack Exchange,提问作者Mjturn
相关产品推荐
相关产品推荐

