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

如何在Custom Tkinter文本框中插入图片?解密程序GUI开发求助

在Custom Tkinter文本框中插入解密后的图片

我正在开发一款解密文件加密数据的程序,要求解密后的数据只能在程序内查看。用Custom Tkinter构建GUI界面,目前遇到技术难题:希望程序能够显示图片,但不知如何将解密后的数据(图片字节)插入到Tkinter文本框中。以下是数据窗口的代码:

import sys
import platform
import os
from cryptography.fernet import Fernet
from customtkinter import *
from CTkListbox import *

global PLATFORM
PLATFORM = platform.system()

with open('bin/main_path.txt', 'r') as file:
    get_path = file.read()

get_path_len = len(get_path)
get_path = get_path[:get_path_len - 7]

sys.path.append(get_path)

# This removes the data widgets when the back button is pressed
def delete_data_widgets():
    from main_menu_module import main_menu
    from main_menu_module import key_path
    from main_menu_module import fernet

    # Delete the widgets from the data menu
    data_frame_left.destroy()
    data_frame_right.destroy()
    main_menu(key_path, fernet)

# This is the command for the listbox in the data menu
def data_listbox_show(selected_option):
    data_textbox.configure(state='normal')
    data_textbox.delete('1.0', 'end')

    index_num = names.index(selected_option)

    data_textbox.insert('end', data_info[index_num])

    print(names[index_num])
    print(names[index_num].split('.', 1)[1])
    
    data_textbox.configure(state='disabled')

# This is the data menu
def data_menu():
    from main_menu_module import fernet
    from main import root

    data = os.listdir('data')
    data_len = len(data)

    global names
    names = []
    global data_info
    data_info = []

    for file in data:
        # Setting up the path to the file
        if PLATFORM == 'Windows':
            file_path = 'data\\' + str(file)
        else:
            file_path = 'data/' + str(file)

        # Opening the file
        with open(file_path, 'rb') as fileR: original = fileR.read()

        # Decrypting the file
        decrypted = fernet.decrypt(original)

        # Filling in the info from the profiles
        data_info.append(decrypted)

        # Decrypting the names
        old_name = bytes(str(file), 'utf-8')
        new_name = str(fernet.decrypt(old_name))
        new_name = new_name[2:]
        new_name = new_name[:-1]

        # Filling in the names of the profiles
        names.append(new_name)

    global data_frame_left
    data_frame_left = CTkFrame(master=root, width=100, height=100)

    global data_back_button
    data_back_button = CTkButton(master=data_frame_left, text='Back', command=delete_data_widgets)
    data_back_button.pack(side=TOP, fill=BOTH)

    global data_listbox
    data_listbox = CTkListbox(master=data_frame_left, command=data_listbox_show, scrollbar_button_color='#1f6aa5', border_color='#1f6aa5')
    data_listbox.pack(side=TOP, fill=BOTH, expand=YES)
    i = 1
    for name in names:
        data_listbox.insert(i, name)
        i = i + 1

    data_frame_left.pack(side=LEFT, fill=BOTH)

    global data_frame_right
    data_frame_right = CTkFrame(master=root)

    global data_textbox
    data_textbox = CTkTextbox(master=data_frame_right, scrollbar_button_color='#1f6aa5', border_color='#1f6aa5')
    data_textbox.pack(side=LEFT, fill=BOTH, expand=YES)
    data_textbox.configure(state='disabled')

    data_frame_right.pack(side=LEFT, fill=BOTH, expand=YES)

解决方法

要在CTkTextbox中插入解密后的图片,需要结合Pillow处理图片字节,再用Tkinter的image_create方法插入。操作步骤如下:

  1. 安装依赖库:先安装Pillow用于图片处理
pip install pillow
  1. 导入必要模块:在代码开头添加以下导入
from PIL import Image, ImageTk
import io
  1. 修改data_listbox_show函数:替换原函数逻辑,增加图片判断与插入功能
def data_listbox_show(selected_option):
    data_textbox.configure(state='normal')
    data_textbox.delete('1.0', 'end')

    index_num = names.index(selected_option)
    file_name = names[index_num]
    decrypted_data = data_info[index_num]
    
    # 定义支持的图片格式后缀
    image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
    # 判断当前选中文件是否为图片
    if any(file_name.lower().endswith(ext) for ext in image_extensions):
        try:
            # 将解密后的字节数据转为PIL Image对象
            img = Image.open(io.BytesIO(decrypted_data))
            # 适配文本框宽度调整图片大小(可选,可根据需求修改)
            textbox_width = data_textbox.winfo_width() - 20  # 留边距
            if img.width > textbox_width:
                scale_ratio = textbox_width / img.width
                new_size = (int(img.width * scale_ratio), int(img.height * scale_ratio))
                img = img.resize(new_size, Image.Resampling.LANCZOS)
            # 转为Tkinter可识别的PhotoImage
            tk_image = ImageTk.PhotoImage(img)
            # 插入图片到文本框末尾
            data_textbox.image_create('end', image=tk_image)
            # 保存图片引用,防止被Python垃圾回收机制销毁
            data_textbox.image_reference = tk_image
        except Exception as e:
            # 图片加载失败时显示错误信息
            data_textbox.insert('end', f"图片加载失败: {str(e)}")
    else:
        # 非图片文件,尝试解码为文本显示
        try:
            text_content = decrypted_data.decode('utf-8')
            data_textbox.insert('end', text_content)
        except UnicodeDecodeError:
            # 无法解码为文本时提示
            data_textbox.insert('end', "该文件无法解码为文本数据")
    
    data_textbox.configure(state='disabled')

关键注意点

  • 保存图片引用:必须将PhotoImage对象赋值给文本框的属性(如data_textbox.image_reference),否则Python会回收这个对象,导致图片无法显示。
  • 图片缩放:根据文本框宽度调整图片大小可以避免图片超出显示区域,也可以根据需求去掉缩放逻辑,让图片保持原始尺寸。
  • 格式兼容:代码中列出了常见的图片格式,可根据需要添加更多格式后缀。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 15:34:54