如何在 tkinter 应用程序中打包和使用图标?
How can I package and use an icon within a tkinter app?
我尝试在 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'],},
)
为了加载我的图标,我尝试了此处描述的不同方法:pkgutil,
importlib.resources。不幸的是 none 他们对我有用。我可能做错了什么。这是我最终得到的代码:
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
。安装后如何更正以显示图标?
首先:package_data
是位于 Python 包中的数据。因此,请确保包含该文件的目录是一个实际的 Python 包(您可能想在其中添加一个 __init__.py
文件),并确保该包已正确添加到您的发行版中(sdist 和 bdist).
所以对于您的情况,类似以下的建议可能会有所帮助:
- 将图片移动到
gui_app/img/icon.gif
- 添加
gui_app/img/__init__.py
(您可能会看到建议说没有必要,如果您真正理解该建议及其含义,请随时遵循)
- 将
gui_app.img
添加到用作 setuptools.setup
函数调用中 packages
参数的参数的列表中
- 相应地调整代码
感谢@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()
我尝试在 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'],},
)
为了加载我的图标,我尝试了此处描述的不同方法:pkgutil, importlib.resources。不幸的是 none 他们对我有用。我可能做错了什么。这是我最终得到的代码:
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
。安装后如何更正以显示图标?
首先:package_data
是位于 Python 包中的数据。因此,请确保包含该文件的目录是一个实际的 Python 包(您可能想在其中添加一个 __init__.py
文件),并确保该包已正确添加到您的发行版中(sdist 和 bdist).
所以对于您的情况,类似以下的建议可能会有所帮助:
- 将图片移动到
gui_app/img/icon.gif
- 添加
gui_app/img/__init__.py
(您可能会看到建议说没有必要,如果您真正理解该建议及其含义,请随时遵循) - 将
gui_app.img
添加到用作setuptools.setup
函数调用中packages
参数的参数的列表中 - 相应地调整代码
感谢@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()