如何在Tkinter中通过for循环展示DataFrame中的字节形式图片?
解决Tkinter循环展示DataFrame中字节图片仅显示最后一张的问题
问题核心原因
- Tkinter的
ImageTk.PhotoImage对象若无持久引用,会被Python垃圾回收机制回收,仅最后一张图片能保留。 - 原代码表头创建逻辑放在循环内,会重复生成表头覆盖之前内容。
- 图片Label的
image参数错误使用str.encode()处理图片对象,导致无法正确识别图片。
修复步骤
- 将表头创建移出循环:遍历DataFrame前一次性创建所有表头标签,避免重复覆盖。
- 正确传入图片对象:直接将
ImageTk.PhotoImage实例赋值给Label的image参数,无需额外编码。 - 保留图片引用:将每个图片对象绑定到对应Label实例(如
pic.image = img),或存入列表维持引用,防止被回收。 - 修正其他逻辑错误:搜索窗口改用
Toplevel()而非Tk(),搜索时获取输入框内容需调用.get(),引用正确的DataFrame变量df_main。
修正后的完整代码
import pandas as pd from PIL import ImageTk, Image from tkinter import * import tkinter as tk from tkinter import filedialog import base64 import io df_main = pd.read_csv("C:/Users/noahk/Documents/Trial.csv") root = Tk() root.title("Fabric Database") root.geometry("400x400") def upload_file(): global lol file = filedialog.askopenfilename() converted_string = base64.b64encode(open(file, "rb").read()) lol = converted_string.decode("utf-8") def submit(): global df_main new_row = { 'Name': name.get(), 'Country': country.get(), 'Price': price.get(), 'Thickness': thickness.get(), 'Fabric Example': lol } df_main = pd.concat([df_main, pd.DataFrame([new_row])], ignore_index=True) print(df_main) def show_pic(): global img, table b = base64.b64decode(lol) img = Image.open(io.BytesIO(b)) img = img.resize((20, 20), Image.ANTIALIAS) img = ImageTk.PhotoImage(img) pic = Label(table, image=img) pic.image = img # 保留引用防止回收 pic.grid(row=1, column=5) def show_table(): global table table = Toplevel() table.title("Fabric Database") table.geometry("600x400") # 加宽窗口适配列数 # 一次性创建表头 headers = ["Name", "Country", "Price", "Thickness", "Fabric Example"] for col, header in enumerate(headers): Label(table, text=header).grid(row=0, column=col, padx=5, pady=5) img_list = [] for x in range(df_main.shape[0]): # 解码并处理图片 b = base64.b64decode(df_main["Fabric Example"][x]) img = Image.open(io.BytesIO(b)) img = img.resize((20, 20), Image.ANTIALIAS) img = ImageTk.PhotoImage(img) img_list.append(img) # 显示文本数据 Label(table, text=df_main["Name"][x]).grid(row=x+1, column=0, padx=5, pady=2) Label(table, text=df_main["Country"][x]).grid(row=x+1, column=1, padx=5, pady=2) Label(table, text=df_main["Price"][x]).grid(row=x+1, column=2, padx=5, pady=2) Label(table, text=df_main["Thickness"][x]).grid(row=x+1, column=3, padx=5, pady=2) # 显示图片并保留引用 pic = Label(table, image=img) pic.image = img # 绑定引用防止回收 pic.grid(row=x+1, column=4, padx=5, pady=2) def search(): search = Toplevel() # 改用Toplevel避免多主窗口 search.title("Fabric Database") search.geometry("600x300") # 创建搜索输入框和标签 headers = ["Name", "Country", "Price", "Thickness", "Fabric Example"] entries = {} for col, header in enumerate(headers): Label(search, text=header).grid(row=0, column=col, padx=5) entry = Entry(search, width=15) entry.grid(row=1, column=col, padx=5) entries[header] = entry def search_table(): # 构建查询条件 query = pd.Series([True]*len(df_main)) for header in headers: val = entries[header].get() if val: query &= (df_main[header] == val) # 显示结果 result_df = df_main[query] # 用文本框显示结果 result_text = Text(search, height=10, width=80) result_text.grid(row=3, column=0, columnspan=5, padx=5, pady=10) result_text.insert(END, result_df.to_string()) Button(search, text="Search", command=search_table).grid(row=2, column=0, columnspan=5, pady=10, ipadx=100) # 主窗口输入控件 name = Entry(root, width=30) name.grid(row=0, column=1, padx=20, pady=(10,0)) country = Entry(root, width=30) country.grid(row=1, column=1) price = Entry(root, width=30) price.grid(row=2, column=1) thickness = Entry(root, width=30) thickness.grid(row=3, column=1) fabric_example = tk.Button(root, text='Upload Files', width=20, command=upload_file) fabric_example.grid(row=4, column=1) # 主窗口标签 Label(root, text="Name").grid(row=0, column=0, pady=(10,0)) Label(root, text="Country").grid(row=1, column=0) Label(root, text="Price").grid(row=2, column=0) Label(root, text="Thickness").grid(row=3, column=0) Label(root, text="Fabric example").grid(row=4, column=0) # 主窗口按钮 submit_btn = Button(root, text="Add to Database", command=submit) submit_btn.grid(row=5, column=0, columnspan=2, pady=10, padx=10, ipadx=105) show_btn = Button(root, text="Press", command=show_pic) show_btn.grid(row=7, column=2) query_btn = Button(root, text="Show Table", command=show_table) query_btn.grid(row=7, column=0, columnspan=2, pady=10, padx=10, ipadx=120) search_btn = Button(root, text="Search Databank", command=search) search_btn.grid(row=12, column=0, columnspan=2, pady=10, padx=10, ipadx=120) root.mainloop()
内容的提问来源于stack exchange,提问作者Imperfected Gaming
相关产品推荐
相关产品推荐

