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

如何为CustomTkinter的CTkToplevel设置iconbitmap?

问题描述

以下是代码示例:

import os
import tkinter
import customtkinter
from PIL import Image

class ToplevelWindow(customtkinter.CTkToplevel):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.geometry("400x300")
        self.title("New Window")
        self.resizable(False, False)
        self.iconbitmap('icon.ico')
        self.after(100, self.lift)

class App(customtkinter.CTk):

    def __init__(self):
        super().__init__()

        self.geometry("550x150")
        self.title("Title")
        self.resizable(False, False)
        logo_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_images")
        self.logo = customtkinter.CTkImage(
            Image.open(os.path.join(logo_path, "MCB.png")),
            size=(90, 54))
        self.labelimage = customtkinter.CTkLabel(master=self, text=None, image=self.logo)
        self.labelimage.place(relx=0, rely=0, anchor=tkinter.NW)

        self.iconbitmap('icon.ico')

        self.button = customtkinter.CTkButton(master=self, text="Close", command=self.close)
        self.button.place(relx=0.675, rely=0.8, anchor=tkinter.CENTER)

        self.button2 = customtkinter.CTkButton(master=self, text="New Window", command=self.open_toplevel)
        self.button2.place(relx=0.325, rely=0.80, anchor=tkinter.CENTER)

        self.toplevel_window = None

    def close(self):
        "nothing here yet"

    def open_toplevel(self):
        if self.toplevel_window is None or not self.toplevel_window.winfo_exists():
            self.toplevel_window = ToplevelWindow(self)  # create window if its None or destroyed
        else:
            self.toplevel_window.focus()  # if window exists focus it

if __name__ == "__main__":
    app = App()
    app.mainloop()

主窗口中使用iconbitmap方法设置图标可正常生效,但在自定义的CTkToplevel子类ToplevelWindow中调用该方法后,图标仍显示为默认样式,无任何效果。请问遗漏了什么?该如何正确设置,或者是否支持此操作?


解决方案

问题原因

CTkToplevel在Windows平台下直接调用self.iconbitmap('icon.ico')无效,主要有两个核心原因:

  1. 相对路径解析问题:如果程序运行时的工作目录和脚本所在目录不一致,相对路径会导致找不到图标文件;
  2. CTkToplevel内部机制:CustomTkinter对窗口做了自定义渲染逻辑,普通iconbitmap调用可能被后续的样式初始化覆盖,且Windows平台下需要指定default参数才能将图标绑定到窗口。

正确设置方法

方法1:绝对路径 + 带default参数的iconbitmap

和主窗口处理logo的逻辑一致,先获取脚本的绝对路径,再拼接图标路径,同时给iconbitmap加上default参数:

class ToplevelWindow(customtkinter.CTkToplevel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.geometry("400x300")
        self.title("New Window")
        self.resizable(False, False)
        
        # 构建图标的绝对路径,避免相对路径错误
        icon_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "icon.ico")
        self.iconbitmap(default=icon_path)
        
        self.after(100, self.lift)

方法2:使用wm_iconphoto(兼容更多格式)

如果上述方法仍不生效,可以尝试tkinter原生的wm_iconphoto方法,结合PIL加载图标(支持ICO、PNG等多种格式):

from PIL import Image, ImageTk

class ToplevelWindow(customtkinter.CTkToplevel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.geometry("400x300")
        self.title("New Window")
        self.resizable(False, False)
        
        icon_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "icon.ico")
        # 用PIL加载图标并转换为tkinter兼容的格式
        icon_img = ImageTk.PhotoImage(Image.open(icon_path))
        # 绑定图标到窗口
        self.wm_iconphoto(True, icon_img)
        
        self.after(100, self.lift)

注意事项

  • 确保图标文件是有效格式:ICO文件需符合Windows规范,避免因文件损坏导致加载失败;
  • 跨平台适配:如果在macOS或Linux运行,需替换为对应平台支持的图标格式(如ICNS、PNG),并调整加载逻辑。

内容的提问来源于stack exchange,提问作者Matheus Assumpção Solinho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 11:02:52