Search code examples
pythonpython-3.xtkintermodulepython-module

Why is my Tkinter image failing to load / be retained when the active file is not __main__?


I am developing a Python application using Tkinter. I have created a module which is essentially a modal to be called elsewhere in the application - in the same file I check if name is main, and I test the modal class if it is. Everything functions, however when I use the module from another file I get the following error:

  File "c:\Users\setas\Documents\KID\V2\TkForge\auth.py", line 57, in _setup_ui
    self.canvas.create_image(170, 24, image=self.image_1)
  File "C:\Users\setas\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2864, in create_image
    return self._create('image', args, kw)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\setas\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2850, in _create
    return self.tk.getint(self.tk.call(
                          ^^^^^^^^^^^^^
_tkinter.TclError: image "pyimage2" doesn't exist

I do not get this error from normal usage.

How I load images

        self.image_1 = tk.PhotoImage(file=load_asset("logo.png", assetArea="auth"))
        self.canvas.create_image(170, 24, image=self.image_1)

load_asset just provides the file path for the asset, an overcomplication I am aware.

How the modules are linked In main.py

import tabs
import header
import auth

# . . .

# Tabs
header_obj = header.Header(canvas)
header_obj.draw(canvas)

In header.py

import tkinter as tk
import tabs
from utilities import load_asset
import auth

class Tab:
    def __init__(self):
        pass

    def draw(self, canvas):
        pass

class Header(Tab):
    def __init__(self, canvas):
        super().__init__()
        self.canvas = canvas
        self.CurrentTab = None
        self.CurrentButton = None
        self.load_images()

    def load_images(self):
        self.image_1 = tk.PhotoImage(file=load_asset("image_1.png"))

    def show_tab(self, button):
        tab = None
        if button == self.ButtonDrawer:
            tab = tabs.Drawer
        elif button == self.ButtonAdmin:
            if auth.AuthWindow().request_auth():
                tab = tabs.Admin
        elif button == self.ButtonLogs:
            tab = tabs.Logs
            
        if tab:
            if self.CurrentTab:
                self.CurrentTab.close()
            self.CurrentTab = tab(self.canvas)
            self.CurrentTab.draw(self.canvas)

I've tried to remove the parts which are irrelevant, however I've attached all the files here: https://github.com/SetAsync/KIDUIConcept Please let me know if I should provide anything else to help locate the issue.

I appreciate any help you can offer, thank you!

I tried to show images on my tkinter project, however could not when called externally.


Solution

  • I resolved the issue by following @TheLizzard's instructions on adding master = self.canvas to both my PhotoImages and Buttons.