1

I have a tkinter based application structured as follows:

import tkinter as tk

class App(tk.Frame):
    def __init__(self, master):
        self.master = master
        tk.Frame.__init__(self, self.master)
        self.configure_gui()
        self.create_widgets()

    def configure_gui(self):
        self.master.iconbitmap("my_logo.ico")
        self.master.title("Example")
        self.master.minsize(250, 50)

    def create_widgets(self):
        self.label = tk.Label(self.master, text="hello world")
        self.label.pack()


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

When I run the .py file from the command line, my logo replaces the default tkinter feather logo in the applications main window as expected. I am even able to freeze and bundle my application with pyinstaller using the following command:

pyinstaller -i my_logo.ico my_application.py

Unfortunately, when I attempt to run the .exe file generated by this process I am met with the following error:

Traceback (most recent call last):
  File "my_application.py", line 22, in <module>
  File "my_application.py", line 7, in __init__
  File "my_application.py", line 11, in configure_gui
  File "tkinter\__init__.py", line 1865, in wm_iconbitmap
_tkinter.TclError: bitmap "my_logo.ico" not defined
[5200] Failed to execute script my_application

I have scoured this site and others in search of a solution that works in my case and have found none. Any direction would be greatly appreciated!

Clade
  • 966
  • 1
  • 6
  • 14
  • 1
    The executable file itself bears the correct logo. So unfortunately, I do not believe that that is the issue. – Clade Nov 20 '19 at 20:18
  • You are correct, I misunderstood the question, `tkinter` can't find the icon because it's not included. I recently posted my workaround here: https://stackoverflow.com/a/58630674/4777984 – tgikal Nov 20 '19 at 21:00

1 Answers1

1

I've found it easier for me just to store the image as a .py module, then PyInstaller handles it like any other module and the basic command line command to make the exe work without anything special:

Script to make image.py file:

import base64
with open("my_logo.ico", "rb") as image:
    b = base64.b64encode(image.read())
with open("image.py", "w") as write_file:
    write_file.write("def icon(): return (" + str(b) + ")"

Then import the module as the image:

import tkinter as tk
import image

class App(tk.Frame):
    def __init__(self, master):
        self.master = master
        tk.Frame.__init__(self, self.master)
        self.configure_gui()
        self.create_widgets()

    def configure_gui(self):
        self.master.tk.call('wm', 'iconphoto', self.master._w, tk.PhotoImage(data=image.icon()))
        self.master.title("Example")
        self.master.minsize(250, 50)

    def create_widgets(self):
        self.label = tk.Label(self.master, text="hello world")
        self.label.pack()


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

Otherwise you basically have to call out adding the .ico file in the build command, then in your script need to add lines to determine where the unpacked pyinstaller-packed script's directory is, then adjust your path to the packed .ico file.

Discussed here: Bundling data files with PyInstaller (--onefile)

But I find my way easier.

tgikal
  • 1,667
  • 1
  • 13
  • 27