You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

CustomTkinter中CTkButton无法正确加载图片的问题排查与解决

CustomTkinter中CTkButton无法正确加载图片的问题排查与解决

最近我用CustomTkinter开发一个工作管理的Python应用,需要创建带图标的按钮。选CustomTkinter本来是看中它的视觉效果,但遇到了个头疼的问题:按钮的图标大部分时候都加载不出来。折腾好一阵终于找到原因,把过程和解决方法分享给大家。

问题重现

先给大家看我最初的核心代码,用来创建带图标的CTkButton:

import customtkinter as ctk
from PIL import Image
import os
from pathlib import Path
import tkinter

directory_base = Path.home() / "AppData" / "Local" / "TestApp"
percorso_icone = os.path.join(directory_base,'Risorse','icone')

img = Image.open(os.path.join(percorso_icone,'icona_cartelle.png'))
cartella_con_elementi = ctk.CTkImage(light_image=img,dark_image=img,size=(40,40))
immagini = {"cartella_con_elementi":cartella_con_elementi}

def crea_pulsante(frame, nome, riga, colonna, resto_laterale):
    global immagini
    # 初始化按钮时未传入image参数
    btn = ctk.CTkButton(master=frame,text=nome,compound='top',fg_color='white',text_color='black',corner_radius=6,cursor='hand2',hover=True)
    btn._text_label.configure(wraplength=150)
    btn.grid(row=riga, column=colonna, padx=resto_laterale, pady=5,sticky='w')
    # 后续通过configure设置图片
    btn.configure(image=immagini["cartella_con_elementi"])
    # 尝试保存图片引用防止被GC回收
    btn.image_associata = immagini["cartella_con_elementi"]
    print(btn.image_associata)
    return btn

root = ctk.CTk()
crea_pulsante(root,'test',2,5,5)
root.mainloop()

运行后控制台能正常打印出CTkImage对象(比如<customtkinter.windows.widgets.image.ctk_image.CTkImage object at 0x0000024935E8C6E0>),但按钮上就是看不到图标。更奇怪的是,把同一个CTkImage用在Label上是完全正常显示的,这说明CTkImage本身没问题,问题出在CTkButton的使用方式上。

排查过程

我一开始以为是Python的GC把图片引用回收了,特意给按钮加了btn.image_associata来保留引用,但还是没用。后来反复对比Label和Button的使用差异,发现了关键:我在初始化CTkButton的时候没有传入image参数,之后再用configure设置就不生效。

解决方法

修改CTkButton的初始化代码,在创建按钮时就传入image参数(哪怕先传一个占位的图片,或者直接传目标图片),之后再用configure修改就可以正常显示了。

修改后的按钮初始化代码:

btn = ctk.CTkButton(master=frame,text=nome,compound='top',fg_color='white',text_color='black',corner_radius=6,cursor='hand2',hover=True,image=immagini["documenti_icona"])

之后再执行btn.configure(image=immagini["cartella_con_elementi"]),按钮的图标就能正常加载显示了。

推测原因是CustomTkinter的CTkButton内部逻辑需要在初始化阶段就存在image属性,后续的configure才能正确识别并渲染图片资源。

内容来源于stack exchange

火山引擎 最新活动