【问题标题】:How can I package and use an icon within a tkinter app?如何在 tkinter 应用程序中打包和使用图标?
【发布时间】:2020-03-22 14:13:56
【问题描述】:

我尝试在tkinter 中安装和运行带有 gui 应用程序的包。安装后我无法显示应用程序图标。我应该改变什么才能使它成为可能?这是我的包目录树:

gui_app/
 | gui_app/
    | __init__.py
    | __main__.py
 | img/
    | icon.gif
 | setup.py

setup.py 包含:

from setuptools import setup
from gui_app import __version__

setup(
    name='gui_app',
    version=__version__,
    packages=['gui_app'],
    data_files=[('', ['img/icon.gif'])],
    entry_points={'gui_scripts': ['gui_app = gui_app.__main__:main'],},
)

为了加载我的图标,我尝试了这里描述的不同方法:pkgutilimportlib.resources。不幸的是,他们都没有为我工作。我可能做错了什么。这是我最终得到的代码:

import tkinter as tk
from importlib.abc import ResourceReader as res

def get_path_before_install():
    return 'img/icon.gif'

def get_path_after_install():
    return res.resource_path('.', 'icon.gif')

def display_gui():
    root = tk.Tk()
    icon_path = get_path_after_install()
    icon = tk.PhotoImage(file=str(icon_path))
    root.iconphoto(False, icon)
    root.mainloop()

def main():
    display_gui()

if __name__ == '__main__': main()

当我使用$ pip install . 然后$ gui_app 它产生FileNotFoundError。安装后如何纠正它以显示图标?

【问题讨论】:

标签: python tkinter setuptools


【解决方案1】:

首先:package_data 是位于 Python 包中的数据。因此,请确保包含该文件的目录是一个实际的 Python 包(您可能希望在其中添加一个 __init__.py 文件),并确保该包已正确添加到您的发行版中(sdist 和 bdist)。

因此,对于您的情况,以下建议可能会有所帮助:

  • 将图片移至gui_app/img/icon.gif
  • 添加gui_app/img/__init__.py(您可能会看到建议说没有必要,如果您真正理解该建议及其含义,请随时遵循它)
  • gui_app.img 添加到用作packages 函数调用中packages 参数的参数的列表中
  • 相应地调整代码

【讨论】:

  • 我已移动图标并添加了__init__.py。然后用gui_app.img 附加包列表。将数据修改为:package_data={'gui_app.img': ['gui_app/img/*.gif'],}, 并使用 res.resource_path('gui_app.img', 'icon.gif')。我仍然得到FileNotFoundError。我在哪里做错了?更新了Github上的代码。
  • 检查您的 sdistbdist 的内容(很可能是 wheel)。确保在两次尝试之间清理*.egg-info 目录。 package_data 参数的参数可能存在问题。也许可以使用以下作为参考来帮助您调试:sinoroc.gitlab.io/kb/python/package_data.html
【解决方案2】:

感谢@sinoroc 的回答和链接材料,我终于找到了适合我的解决方案。首先我对目录结构进行了更改(移动了icon.gif并添加了MANIFEST.in):

gui_app/
 | gui_app/
    | __init__.py
    | __main__.py
    | icon.gif
 | MANIFEST.in
 | setup.py

然后在MANIFEST.in 中添加一行include gui_app/icon.gif。接下来,我将setup.py 中的package_data 替换为include_package_data=True。这是修改后的文件:

from setuptools import setup
from gui_app import __version__

setup(
    name='gui_app',
    version=__version__,
    packages=['gui_app'],
    include_package_data=True,
    entry_points={'gui_scripts': ['gui_app = gui_app.__main__:main'],},
)

我终于摆脱了ResourceReader.resource_path('gui_app', 'icon.gif')。我用pkgutil.get_data('gui_app', 'icon.gif')代替了他。 __main__.py 现在包含:

import tkinter as tk
import pkgutil

def get_icon():
    return pkgutil.get_data('gui_app', 'icon.gif')

def display_gui():
    root = tk.Tk()
    icon = tk.PhotoImage(data=get_icon())
    root.iconphoto(False, icon)
    root.mainloop()

def main():
    display_gui()

if __name__ == '__main__': main()

【讨论】:

    猜你喜欢
    • 2016-01-13
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 2019-02-14
    • 2020-08-29
    相关资源
    最近更新 更多