Tkinter实现点击Listbox项在frame3显示对应国家图片的方法
实现逻辑说明
要实现点击列表项显示对应国家图片的效果,核心走3个环节即可:
- 给国家列表的Listbox组件绑定选中事件,用户点选任意列表项时自动触发自定义处理函数
- 提前准备好对应国家的图片资源,统一命名规则方便和列表里的国家名匹配;注意tkinter加载图片有个常见坑:图片对象必须赋值给持久存在的变量(不能是函数内的临时变量),否则会被Python垃圾回收机制回收,最终显示空白
- 事件触发时读取当前选中的国家名,加载对应图片,渲染到frame3区域预留的Label组件上即可
具体修改步骤
- 清理无用导入:原代码里
from turtle import position, right完全没有用到,直接删除即可 - 准备资源:在脚本同目录新建
flags文件夹,把所有国家对应的国旗图片放进去,图片直接以国家名命名(比如Philippines.png、Malaysia.png),建议优先用gif或png格式,tkinter原生支持无需额外依赖;如果要使用jpg格式,需要先安装Pillow库做格式转换 - 新增全局变量存储当前显示的图片对象,避免被垃圾回收
- 给Listbox组件绑定
<<ListboxSelect>>选中事件,绑定到自定义的图片加载函数 - 编写事件处理函数:读取选中的国家名、加载对应图片、更新frame3里Label的显示内容
修改后完整代码
from tkinter import * root = Tk() root.title("LT_DelosSantosCristianJay") root.geometry("500x300") # 全局变量存当前显示的国旗图片,防止被垃圾回收导致显示空白 current_flag = None #FRAMES frame_1 = Frame(root) frame_1.grid(row = 0, column = 0, columnspan = 2, padx=20, pady=10) frame_2 = Frame(root) frame_2.grid(row = 1, column = 0,pady=(0,20), padx=20) frame_3 = Frame(root) frame_3.grid(row = 1, column = 1, padx=20) continents = { "Asia": ["Philippines", "Malaysia", "Taiwan", "Singapore", "Thailand", "India"], "Africa": ["Algeria", "Angola", "Egypt", "Cape Verde", "Liberia", "Kenya", "Morocco", "Nigeria"], "America": ["Venezuela", "Peru", "Jamaica", "United States", "Cuba", "Chile", "Argentina"], "Europe": ["Russia", "Germany", "United Kingdom", "Italy", "Ukraine", "France", "Belgium"] } # Frame One var = StringVar() var.set('Select') Radiobutton(frame_1, text="Asia", font=("Times", 12, "bold"), fg="blue", variable=var, value='Asia', borderwidth=1, relief=SOLID, width=10, command=lambda: RadioSelected(var.get())).pack(side=LEFT) Radiobutton(frame_1, text="Africa", font=("Times", 12, "bold"), fg="blue", variable=var, value="Africa", borderwidth=1, relief=SOLID, width=11, command=lambda: RadioSelected(var.get())).pack(side=LEFT) Radiobutton(frame_1, text="America", font=("Times", 12, "bold"), fg="blue", variable=var, value="America", borderwidth=1, relief=SOLID, width=11, command=lambda: RadioSelected(var.get())).pack(side=LEFT) Radiobutton(frame_1, text="Europe", font=("Times", 12, "bold"), fg="blue", variable=var, value="Europe", borderwidth=1, relief=SOLID, width=11, command=lambda: RadioSelected(var.get())).pack(side=LEFT) # Frame Two # Listbox and Scrollbar flag_listbox = Listbox(frame_2, font=("Times",15,"bold"),width=15,height=7) flag_listbox.pack(side=LEFT, fill=BOTH) flag_scrollbar = Scrollbar(frame_2) flag_scrollbar.pack(side=RIGHT, fill=BOTH) flag_listbox.config(yscrollcommand=flag_scrollbar.set) flag_scrollbar.config(command=flag_listbox.yview) # 列表选中事件:点击国家时加载对应国旗 def OnCountrySelect(event): global current_flag # 判断是否有选中项,避免空选时报错 if not flag_listbox.curselection(): return selected_idx = flag_listbox.curselection()[0] selected_country = flag_listbox.get(selected_idx) # 按命名规则拼接图片路径,这里默认图片是png格式存在flags文件夹下 img_path = f"flags/{selected_country}.png" # 加载图片、调整尺寸适配显示区域 current_flag = PhotoImage(file=img_path).subsample(2,2) # 更新Label显示图片 flagbox_Label.config(image=current_flag) # 给Listbox绑定选中事件 flag_listbox.bind("<<ListboxSelect>>", OnCountrySelect) # Radio Button click def RadioSelected(Value): flag_listbox.delete(0, END) # 切换大洲时清空之前显示的国旗 global current_flag current_flag = None flagbox_Label.config(image='') list_values = continents[Value] for i in list_values: flag_listbox.insert(END, i) #Frame Three flagbox_Label = Label(frame_3,bg="white",width=150,height=150) flagbox_Label.grid(sticky="we",pady=(0,20)) root.mainloop()
注意事项
- 图片路径不要写错,如果不想建文件夹,直接把图片放在脚本同目录,把代码里的
f"flags/{selected_country}.png"改成f"{selected_country}.png"即可 - 如果图片尺寸过大,可以调整
subsample(2,2)里的参数,数值越大图片缩放比例越高 - 如果需要显示jpg格式图片,把图片加载部分的代码替换成Pillow库的加载逻辑即可,示例:
from PIL import Image, ImageTk # 替换原来的PhotoImage加载逻辑 img = Image.open(img_path).resize((150,150)) current_flag = ImageTk.PhotoImage(img)
内容的提问来源于stack exchange,提问作者Jay Delos Santos
相关产品推荐
相关产品推荐

