Как я могу упаковать и использовать значок в приложении tkinter? - PullRequest
0 голосов
/ 22 марта 2020

Я пытаюсь установить и запустить пакет с приложением gui в tkinter. Я не могу отобразить значок приложения после установки. Что я должен изменить, чтобы сделать это возможным? Вот мое дерево каталогов пакетов:

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 . К сожалению, никто из них не работал для меня. Я могу сделать что-то не так. Вот код, с которым я закончил:

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. Как я могу исправить это, чтобы отобразить значок после установки?

Ответы [ 2 ]

0 голосов
/ 23 марта 2020

Благодаря ответу @ sinoro c и связанным материалам я наконец-то нашел для меня рабочее решение. Сначала я внес изменения в структуру каталогов (переместил icon.gif и добавил MANIFEST.in):

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

Затем добавил одну строку include gui_app/icon.gif в MANIFEST.in. Затем я заменил package_data в setup.py просто 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()
0 голосов
/ 23 марта 2020

Первое: package_data - данные, находящиеся в пакете Python. Поэтому убедитесь, что каталог, содержащий файл, является действительным пакетом Python (возможно, вы захотите добавить туда файл __init__.py), и убедитесь, что этот пакет правильно добавлен в ваши дистрибутивы ( sdist и bdist ).

Так что, вероятно, для вашего случая может помочь что-то вроде следующих рекомендаций:

  • переместить изображение в gui_app/img/icon.gif
  • добавьте gui_app/img/__init__.py (вы можете увидеть совет, который говорит, что он не нужен, если вы действительно понимаете этот совет и его значение, а затем смело следуйте ему)
  • добавьте gui_app.img в список, используемый в качестве аргумента для packages параметр в вызове функции setuptools.setup
  • настроить код соответственно
...