Tkinter猜牌游戏更新图片首次成功 二次调用报PhotoImage无configure属性错误
问题修复方案
核心错误原因
报错的直接原因是你在get_new_card函数中错误覆盖了label_image变量:
首次调用get_new_card时,label_image是你初始化创建的tk.Label控件对象,调用configure方法正常;但执行完label_image.configure(image=new_card)之后,你写了label_image = new_card,直接把全局的label_image变量赋值成了ImageTk.PhotoImage类型的图片对象,第二次调用get_new_card时,自然就不存在configure方法了。
同时你的代码还存在两个需要同步修复的问题:
- Tkinter图片引用丢失问题:PhotoImage对象如果没有被持续引用,会被Python垃圾回收,导致界面上图片显示空白,需要单独用全局变量保存当前使用的图片对象
- 业务逻辑错误:当前代码不管玩家猜测对错都会累加正确次数,且直接比较文件名字符串判断点数大小的逻辑错误,需要提取文件名中的数字转为整数再比较
具体修复步骤
- 新增全局变量保存当前图片引用,不要覆盖
label_image这个Label控件变量 - 删除
get_new_card中label_image = new_card这行错误代码,改为用新增的全局变量保存新生成的图片对象 - 修正猜牌判断逻辑:提取文件名中的数字转为整数后再比较大小,猜对调用
count_right,猜错调用count_wrong - 修正代码中原有的缩进错误
修正后完整代码
import tkinter as tk from PIL import ImageTk, Image import random # increase right counter def count_right(): global right_num right_num.set(right_num.get() + 1) print("Count 'Right guesses' increased") # increase wrong counter def count_wrong(): global wrong_num wrong_num.set(wrong_num.get() + 1) print("Count 'Wrong guesses' increased") # GUI window = tk.Tk() window.title('Guess the card') window.geometry('300x480') window.resizable(False, False) # DEFINITIONS # define counter variables right_num = tk.IntVar() wrong_num = tk.IntVar() right_num.set(0) wrong_num.set(0) # define labels label_top = tk.Label(text='Will the next card be higher or lower?', width=30, height=3) label_right = tk.Label(text='Right guesses:', width=50, height=2) label_right_num = tk.Label(textvariable=right_num, width=50, height=2) label_wrong = tk.Label(text='Wrong guesses:', width=50, height=2) label_wrong_num = tk.Label(textvariable=wrong_num, width=50, height=2) label_space1 = tk.Label(text='', width=50, height=1) label_space2 = tk.Label(text='', width=50, height=1) # image # program opens the same card when opening current_img = '26.jpg' previous_img = '' img_start = ImageTk.PhotoImage(Image.open(current_img)) current_photo = img_start # 保存图片引用,防止被GC回收 label_image = tk.Label(image = img_start) #function to change image def get_new_card(): global label_image, current_img, previous_img, current_photo # save state of current card previous_img = current_img # gen new card current_img = str(random.randint(1, 52)) + '.jpg' new_card = ImageTk.PhotoImage(Image.open(current_img)) label_image.configure(image=new_card) current_photo = new_card # 更新图片引用 print('Card updated') def press_higher(): global current_img, previous_img # check if new card higher or lower than previous card get_new_card() current_num = int(current_img.split('.')[0]) prev_num = int(previous_img.split('.')[0]) if current_num > prev_num: count_right() else: count_wrong() def press_lower(): global current_img, previous_img # check if new card higher or lower than previous card get_new_card() current_num = int(current_img.split('.')[0]) prev_num = int(previous_img.split('.')[0]) if current_num < prev_num: count_right() else: count_wrong() # define buttons button_higher = tk.Button(text='Higher', width=15, height=2, command = press_higher) button_lower = tk.Button(text='Lower', width=15, height=2, command = press_lower) # PACKS: label_top.pack() label_image.pack() label_space2.pack() button_higher.pack() button_lower.pack() label_space1.pack() label_right.pack() label_right_num.pack() label_wrong.pack() label_wrong_num.pack() # create mainloop to keep running the script window.mainloop()
内容的提问来源于stack exchange,提问作者Criomby
相关产品推荐
相关产品推荐

