Tkinter点击菜品按钮展示对应图片时始终显示最后一张图片如何解决
问题原因
你遇到的问题由两个错误共同导致:
- 生成菜品按钮时没有将菜品对应的图片序号绑定到点击回调,点击按钮后程序不知道你要加载哪张图片
- 原图片展示函数中循环加载了所有菜品的图片,且反复覆盖
canvas.gif1这个图片引用,tkinter要求图片对象必须持续持有引用才会正常渲染,最终只有最后一张图的引用被保留,所以不管点哪个按钮都只显示最后一张图
修改方案
步骤1:改造按钮生成逻辑,绑定对应图片序号
在读取菜品数据生成按钮时,新增索引计数器,通过lambda默认参数将当前序号绑定到回调函数,解决循环变量迟绑定的问题:
def create_widgets(self): if (self.x == 2): param = "coucou" self.hi_there = tk.Label(self) self.hi_there["text"] = param self.hi_there.pack(side="top") self.quit = tk.Button(self, text="QUIT", fg="red", command=self.master.destroy) self.quit.pack(side="bottom") # 推荐用with语句打开文件,自动处理关闭逻辑 with open('data.txt',"r") as File: idx = 0 # 新增:记录当前菜品的行索引,和图片序号一一对应 while(True): record = File.readline() if (record == ''): break data = record.split(',') print('Name of the dish:', data[0]) dish_btn = tk.Button(self) dish_btn["text"] = data[0] # 把当前索引绑定到回调的默认参数,避免循环变量迟绑定问题 dish_btn["command"] = lambda dish_idx=idx: self.photoOfTheDish(dish_idx) dish_btn.pack(side="top") # 打印、展示配料的逻辑不变 for i in range(1, len(data)): print('Ingredients:',data[i]) ing_label = tk.Label(self) ing_label["text"] = data[i] ing_label.pack(side="top") idx += 1 # 处理完一行索引自增
步骤2:改造图片展示函数,只加载对应序号的图片
修改photoOfTheDish函数,接收传入的菜品序号,仅加载对应序号的单张图片:
def photoOfTheDish(self, dish_idx): novi = Toplevel() canvas = Canvas(novi, width = 1500, height = 1000) canvas.pack(expand = YES, fill = BOTH) # 直接用传入的序号拼文件名,不需要统计行数、循环加载所有图片 target_img = PhotoImage(file = str(dish_idx) + ".ppm") canvas.create_image(50, 10, image = target_img, anchor = NW) # 保留图片引用,避免被GC回收导致无法显示 canvas.img_ref = target_img
注意事项
需要保证data.txt中菜品的行顺序和图片命名完全对应:第0行菜品对应0.ppm,第1行对应1.ppm,以此类推。
内容的提问来源于stack exchange,提问作者Camille BOUQUET
相关产品推荐
相关产品推荐

