Python Tkinter读取Oracle BLOB字段显示图片的实现方法
问题背景
通过Python读取Oracle表数据填充Tkinter界面控件时,表中BLOB类型的员工照片字段无法正常加载展示,目前EMPLOYEE_ID、FIRST_NAME两个文本字段已可正常读取填充,原实现代码如下:
import cx_Oracle from tkinter import * root = Tk() con = cx_Oracle.connect('hr/hr@localhost/orcl') cur = con.cursor() cur.execute("SELECT EMPLOYEE_ID, FIRST_NAME, photo FROM HR.EMP WHERE EMPLOYEE_ID = 3000") row = cur.fetchone() print(cur.rowcount) if cur.rowcount > 0: print('Row retrieved successfully.') else: print('Data Retrieval failed.') photo = image_types() EMPLOYEE_ID = NUMERIC FIRST_NAME = StringVar cursor = con.cursor() employee_id_entry = Entry(textvariable=EMPLOYEE_ID, width="30", background='BLUE') first_name_entry = Entry(textvariable=FIRST_NAME, width="30", background='YELLOW') photo_entry = Entry(textvariable=photo, width="30", background='GREEN') employee_id_entry.place(x=10, y=10) first_name_entry.place(x=10, y=30) photo_entry.place(x=10, y=50) employee_id_entry.insert(0, row[0]) first_name_entry.insert(0, row[1]) # photo_entry.insert(END, row[2]) cursor.close() con.close() root.mainloop()
现存问题
- 误用
Entry文本输入框承载图片:Entry仅支持文本内容展示,无法渲染图片,需要使用Label控件作为图片载体 - BLOB数据未做格式转换:Oracle读取到的BLOB字段是原始二进制流,Tkinter无法直接识别,需要通过图片处理库转换为兼容的图片对象
- 存在大量无效定义:原代码中
image_types()、NUMERIC为不存在的方法/类型,StringVar未做实例化,重复创建多余cursor,都会直接触发运行错误 - 未处理Tkinter图片回收机制:Tkinter图片对象若无持久引用会被垃圾回收机制自动回收,导致图片显示空白
解决步骤
- 安装依赖库:除
cx_Oracle和Tkinter外,需要安装Pillow处理图片二进制流,执行安装命令pip install pillow - 读取BLOB二进制内容:调用BLOB对象的
read()方法拿到完整图片二进制数据,通过内存字节流对象承载,无需写入本地磁盘 - 转换图片格式:用Pillow加载内存中的二进制图片,转为Tkinter可识别的
ImageTk.PhotoImage对象 - 绑定图片引用:将转换后的图片对象绑定到展示控件的属性上,避免被垃圾回收
- 清理原代码中的无效变量和冗余逻辑
修正后完整代码
import cx_Oracle from tkinter import * from PIL import Image, ImageTk from io import BytesIO root = Tk() root.geometry("350x250") # 适配控件和图片尺寸调整窗口大小 # 数据库连接和查询 con = cx_Oracle.connect('hr/hr@localhost/orcl') cur = con.cursor() cur.execute("SELECT EMPLOYEE_ID, FIRST_NAME, photo FROM HR.EMP WHERE EMPLOYEE_ID = 3000") row = cur.fetchone() # 文本字段填充 employee_id_entry = Entry(width=30, background='BLUE') first_name_entry = Entry(width=30, background='YELLOW') employee_id_entry.place(x=10, y=10) first_name_entry.place(x=10, y=30) if row: employee_id_entry.insert(0, row[0]) first_name_entry.insert(0, row[1]) # 处理BLOB图片 blob_data = row[2].read() # 读取BLOB二进制内容 image_stream = BytesIO(blob_data) # 转内存字节流 pil_image = Image.open(image_stream) # 可根据需要调整图片尺寸,例:缩放到宽120高150 pil_image = pil_image.resize((120, 150), Image.Resampling.LANCZOS) tk_photo = ImageTk.PhotoImage(pil_image) # 用Label展示图片 photo_label = Label(root, image=tk_photo) photo_label.image = tk_photo # 绑定引用防止被GC回收 photo_label.place(x=10, y=70) # 关闭数据库连接 cur.close() con.close() root.mainloop()
注意:如果BLOB中存储的图片格式不是Pillow支持的通用格式(jpg/png等),需要先对应做格式解码。
内容的提问来源于stack exchange,提问作者SeyedG
相关产品推荐
相关产品推荐

