You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编码/解码图片用于存储?Tkinter新窗口显示图片报pyimagexy不存在错误

问题解决:Tkinter子窗口图片显示失败与图片存储优化

核心问题分析

  1. 多Tk实例冲突:创建新窗口时用Tk()会生成独立的Tkinter主循环,导致PhotoImage资源无法跨实例共享,触发pyimagexy does not exist错误。
  2. PhotoImage被GC回收:Tkinter的PhotoImage如果没有被Python变量持有,会被垃圾回收器清理,导致图片无法显示。
  3. Base64存储格式错误:直接将bytes类型的base64编码转字符串会保留b'...'前缀,解码时会出错。
  4. 搜索函数逻辑错误:搜索时直接用Entry对象而非输入值,且引用了未定义的df变量。

修复方案与修改后代码

关键修改点

  • 用Toplevel()替代Tk()创建子窗口,共享主窗口的Tk上下文
  • 为Label绑定PhotoImage引用(pic.image = img),避免被回收
  • 修正Base64编码的存储与解码逻辑,存储纯字符串而非带b''的字节串表示
  • 修复搜索函数的变量引用与取值逻辑
import tkinter as tk
from tkinter import filedialog
import base64
from PIL import Image, ImageTk
import io
import pandas as pd

global df_main

root = tk.Tk()
root.title("Fabric Database")
root.geometry("400x400")
df_main = pd.read_csv("C:/Users/noahk/Documents/Trial.csv")

print(df_main)

def upload_file():
    global converted_string
    file = filedialog.askopenfilename()
    # 将图片编码为base64字符串(去掉b''前缀)
    converted_string = base64.b64encode(open(file, "rb").read()).decode('utf-8')

def submit():
    global df_main
    # 存储纯base64字符串
    df_main = df_main.append({
        'Name': str(name.get()), 
        'Country': str(country.get()), 
        'Price': str(price.get()), 
        'Thickness':str(thickness.get()), 
        'Fabric Example': converted_string
    }, ignore_index = True)    

def show_pic():
    global img
    # 解码时转回bytes
    b = base64.b64decode(converted_string.encode('utf-8'))
    img = Image.open(io.BytesIO(b))
    img = img.resize((20, 20), Image.ANTIALIAS)
    img = ImageTk.PhotoImage(img)
    pic = tk.Label(root, image=img)
    pic.image = img  # 保留引用防止GC回收
    pic.grid(row=1,column=5)

def show_table():
    global img, pic
    # 用Toplevel创建子窗口,关联主窗口
    table = tk.Toplevel(root)
    table.title("Fabric Database")
    table.geometry("400x400")
    
    # 解码图片
    b = base64.b64decode(converted_string.encode('utf-8'))
    img = Image.open(io.BytesIO(b))
    img = img.resize((20, 20), Image.ANTIALIAS)
    img = ImageTk.PhotoImage(img)
    
    pic = tk.Label(table, image=img)
    pic.image = img  # 绑定引用
    pic.grid(row=1,column=5)
    
    # 表格表头
    table_name = tk.Label(table, text="Name")
    table_name.grid(row=0,column=0)
    table_Country = tk.Label(table, text="Country")
    table_Country.grid(row=0,column=1)
    table_Price = tk.Label(table, text="Price")
    table_Price.grid(row=0,column=2)
    table_Thickness = tk.Label(table, text="Thickness")
    table_Thickness.grid(row=0,column=3)
    table_Fabric = tk.Label(table, text="Fabric Example")
    table_Fabric.grid(row=0,column=4)
    
    # 表格内容
    df_name_label = tk.Label(table, text=df_main["Name"])
    df_name_label.grid(row=1,column=0)
    df_Countrylabel = tk.Label(table, text=df_main["Country"])
    df_Countrylabel.grid(row=1,column=1)
    df_Pricelabel = tk.Label(table, text=df_main["Price"])
    df_Pricelabel.grid(row=1,column=2)
    df_Thicknesslabel = tk.Label(table, text=df_main["Thickness"])
    df_Thicknesslabel.grid(row=1,column=3)

def search():
    # 用Toplevel创建搜索窗口
    search_win = tk.Toplevel(root)
    search_win.title("Fabric Database")
    search_win.geometry("400x400")
    
    # 定义搜索输入框(用局部变量+窗口属性存储,避免全局变量滥用)
    search_win.name_table = tk.Entry(search_win, width=30)
    search_win.name_table.grid(row=2, column=0)
    search_win.country_table = tk.Entry(search_win, width=30)
    search_win.country_table.grid(row=2, column=1)
    search_win.price_table = tk.Entry(search_win, width=30)
    search_win.price_table.grid(row=2, column=2)
    search_win.thickness_table = tk.Entry(search_win, width=30)
    search_win.thickness_table.grid(row=2, column=3)
    search_win.fabric_example_table = tk.Entry(search_win, width=30)
    search_win.fabric_example_table.grid(row=2, column=4)
    
    # 表头标签
    name_label_table = tk.Label(search_win, text="Name")
    name_label_table.grid(row=1, column=0)
    country_label_table = tk.Label(search_win, text="Country")
    country_label_table.grid(row=1, column=1)
    price_label_table = tk.Label(search_win, text="Price")
    price_label_table.grid(row=1, column=2)
    thickness_label_table = tk.Label(search_win, text="Thickness")
    thickness_label_table.grid(row=1, column=3)
    fabric_example_label_table = tk.Label(search_win, text="Fabric example")
    fabric_example_label_table.grid(row=1, column=4)
    
    # 搜索按钮,绑定搜索窗口到回调
    search_btn = tk.Button(search_win, text="Search", command=lambda: search_table(search_win))
    search_btn.grid(row=3,column=0,columnspan=2,pady=10,padx=10,ipadx=120)

def search_table(search_win):
    # 获取输入框的值,用df_main而非未定义的df
    stdf = df_main[
        (df_main["Name"] == search_win.name_table.get()) & 
        (df_main["Country"] == search_win.country_table.get()) & 
        (df_main["Price"] == search_win.price_table.get()) &
        (df_main["Thickness"] == search_win.thickness_table.get()) &
        (df_main["Fabric Example"] == search_win.fabric_example_table.get())
    ]
    stdf_label = tk.Label(search_win, text=stdf)
    stdf_label.grid(row=12,column=1)

# 主窗口输入控件
name = tk.Entry(root, width=30)
name.grid(row=0, column=1, padx=20, pady=(10,0))
country = tk.Entry(root, width=30)
country.grid(row=1, column=1)
price = tk.Entry(root, width=30)
price.grid(row=2, column=1)
thickness = tk.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)

show_btn = tk.Button(root, text="Press", command=show_pic)
show_btn.grid(row=7,column=2)

# 主窗口标签
name_label = tk.Label(root, text="Name")
name_label.grid(row=0, column=0, pady=(10,0))
country_label = tk.Label(root, text="Country")
country_label.grid(row=1, column=0)
price_label = tk.Label(root, text="Price")
price_label.grid(row=2, column=0)
thickness_label = tk.Label(root, text="Thickness")
thickness_label.grid(row=3, column=0)
fabric_example_label = tk.Label(root, text="Fabric example")
fabric_example_label.grid(row=4, column=0)

delete_box = tk.Entry(root, width=30)
delete_box.grid(row=9,column=1,pady=5)
delete_box_label=tk.Label(root, text="Select Row ID")
delete_box_label.grid(row=9,column=0, pady=5)

# 主窗口按钮
submit_btn = tk.Button(root, text="Add to Database", command=submit)
submit_btn.grid(row=5,column=0,columnspan=2,pady=10,padx=10,ipadx=105)

query_btn = tk.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 = tk.Button(root, text="Search Databank", command=search)
search_btn.grid(row=12,column=0,columnspan=2,pady=10,padx=10,ipadx=120)

root.mainloop()

额外说明

  • 去掉了不必要的全局变量,改用窗口属性存储搜索输入框,减少全局变量滥用
  • 简化了upload_file的lambda调用,直接用upload_file即可
  • 修复了搜索函数中未定义的df变量,改为使用全局的df_main

内容的提问来源于stack exchange,提问作者Imperfected Gaming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:01:12