跳转至

tkflu.icons · icons 窗口图标

窗口 / 任务栏图标。

图标以 base64 PNG 的形式内嵌在本模块里,因此不依赖任何资源文件。

旧实现的问题

icon() / light() / dark() 每次调用都会 mkstemp() 一个新的临时 文件,而且 从不关闭 mkstemp 返回的文件描述符:

  • 每创建一个窗口就泄漏一个句柄(Windows 上有句柄上限);
  • 每创建一个窗口就在系统临时目录里留下一个残留文件;
  • 而这些图标数据本来就是固定的,完全没必要每次重新解码、重新落盘。

现在的做法

  • :func:icon_photoimage —— 推荐。直接用 base64 建 PhotoImage, 完全不碰磁盘(Tk 8.6 原生支持 PNG)。
  • :func:icon / :func:light / :func:dark —— 保持"返回文件路径"的历史行为, 但按图标名缓存路径:进程内每个图标只落盘一次,并且关闭 fd。

dark()

深色主题图标的文件路径(历史 API,见模块文档)。

源代码位于: tkflu\icons.py
 98
 99
100
def dark() -> str:
    """深色主题图标的文件路径(历史 API,见模块文档)。"""
    return _materialize("dark")

icon()

默认应用图标的文件路径(历史 API,见模块文档)。

源代码位于: tkflu\icons.py
88
89
90
def icon() -> str:
    """默认应用图标的文件路径(历史 API,见模块文档)。"""
    return _materialize("icon")

icon_data(name='light')

返回图标的 base64 数据(不落盘)。

源代码位于: tkflu\icons.py
68
69
70
def icon_data(name: str = "light") -> bytes:
    """返回图标的 base64 数据(不落盘)。"""
    return _icon_bytes(name)

icon_photoimage(name='light', master=None)

直接用内嵌 base64 建 PhotoImage,完全不落盘。

:param name: "light" / "dark" / "icon" :param master: 目标控件;多解释器场景必须传,否则图片会挂到默认根窗口

.. warning:: 这里刻意不做进程级缓存。

早先按 (id(tk), name) 缓存过一份 PhotoImage,看起来省了一次 解码,代价却很大:

  • PhotoImage 与它的 Tk 解释器同生共死,缓存里留一张就等于 让整个解释器无法回收——实测反复开关窗口 50 次,内存涨了 ~96 MB(清掉缓存后只涨 ~12 MB);
  • id() 会被复用。解释器销毁后 id 可能被下一个解释器占用, 于是拿到的是一张属于已死解释器的图片,报 "not a photo image"。

解码内嵌的 base64 很便宜,而调用方(FluWindow / FluToplevel) 本来就用 self._icon_photo 持着引用,不需要这里再存一份。

源代码位于: tkflu\icons.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
def icon_photoimage(name: str = "light", master=None):
    """直接用内嵌 base64 建 ``PhotoImage``,**完全不落盘**。

    :param name: ``"light"`` / ``"dark"`` / ``"icon"``
    :param master: 目标控件;**多解释器场景必须传**,否则图片会挂到默认根窗口

    .. warning::
       这里**刻意不做进程级缓存**。

       早先按 ``(id(tk), name)`` 缓存过一份 ``PhotoImage``,看起来省了一次
       解码,代价却很大:

       * ``PhotoImage`` 与它的 Tk 解释器同生共死,缓存里留一张就等于
         **让整个解释器无法回收**——实测反复开关窗口 50 次,内存涨了
         ~96 MB(清掉缓存后只涨 ~12 MB);
       * ``id()`` 会被复用。解释器销毁后 id 可能被下一个解释器占用,
         于是拿到的是一张属于**已死解释器**的图片,报 "not a photo image"。

       解码内嵌的 base64 很便宜,而调用方(``FluWindow`` / ``FluToplevel``)
       本来就用 ``self._icon_photo`` 持着引用,不需要这里再存一份。
    """
    from tkinter import PhotoImage

    return PhotoImage(data=_icon_bytes(name), master=master)

light()

浅色主题图标的文件路径(历史 API,见模块文档)。

源代码位于: tkflu\icons.py
93
94
95
def light() -> str:
    """浅色主题图标的文件路径(历史 API,见模块文档)。"""
    return _materialize("light")