Python: Tkinter iconbitmap assignment only works at module level

ghz 12hours ago ⋅ 9 views

I'm using a tkinter.ttk window and I'm using an icon to set the iconbitmap of my window. However root.iconbitmap() is ignored on Windows 10. But There is an easy way to avoid an error: root.tkinter.call('wm', 'iconphoto', root._w, icon)

So:

from tkinter import *
from tkinter.ttk import *

root=Tk()
root.call('wm', 'iconphoto', root._w, icon)

works. BUT:

def func():
    root=Tk()
    root.call('wm', 'iconphoto', root._w, icon)

does NOT work. An error occurs. It's interesting that that error is exactly the same one that occurs when you use root.iconbitmap():

Traceback (most recent call last):
File "E:\test.py", line 95, in <module>
func()
File "E:\test.py", line 36, in func
t.call('wm', 'iconphoto', t._w, icon)
_tkinter.TclError: can't use "pyimagex" as iconphoto: not a photo Image

And there is one interesting fact left: In another file I tried to use it as a function too, it worked. In the new file (test.py) it didn't work (and it was the same function). Does anybody know why it doesn't work and what I can do to avoid an error? Thanks in advance...

Answer

The error you're encountering, _tkinter.TclError: can't use "pyimagex" as iconphoto: not a photo Image, typically occurs when the image passed to the iconphoto method is not in the correct format expected by Tkinter for setting an icon.

In the case of root.call('wm', 'iconphoto', root._w, icon), the icon variable is likely an object of type PhotoImage or BitmapImage, which Tkinter can use as a window icon. However, based on the error message, it seems like the icon you're passing may not be in the expected format (likely, it's not a valid PhotoImage or BitmapImage object).

Understanding the Issue:

The key issue here is that the iconphoto method expects a PhotoImage or BitmapImage object, but it seems like your icon variable is not one of these types when you're calling it inside your function func(). You may not be defining or loading the image correctly in the function, which could lead to the error.

The reason why the code works when you directly call root.call('wm', 'iconphoto', root._w, icon) might be because icon is already properly initialized (outside of the function), but inside the function, the icon object may not have been properly initialized.

Solution:

  1. Make Sure the icon Image is Loaded Correctly: You should load the image properly before calling iconphoto. Here's an updated example where the image is correctly loaded:
from tkinter import *
from tkinter.ttk import *
from tkinter import PhotoImage

def func():
    root = Tk()
    
    # Load the image before using it as an icon
    icon = PhotoImage(file="path_to_your_icon.png")
    
    # Set the icon using iconphoto
    root.call('wm', 'iconphoto', root._w, icon)
    
    root.mainloop()

# Calling the function
func()
  1. Explanation:

    • PhotoImage(file="path_to_your_icon.png"): Make sure you're loading the image as a PhotoImage object (this is typically required for iconphoto).
    • root.call('wm', 'iconphoto', root._w, icon): Once the image is correctly loaded, you can use it as the window icon.
  2. Ensure Correct Image Format: If you're trying to use a .ico file or another format, Tkinter may not support that directly. For .ico files, you should use BitmapImage instead:

from tkinter import *
from tkinter.ttk import *
from tkinter import BitmapImage

def func():
    root = Tk()
    
    # Load an .ico image file for Windows
    icon = BitmapImage(file="path_to_your_icon.ico")
    
    # Set the icon using iconphoto
    root.call('wm', 'iconphoto', root._w, icon)
    
    root.mainloop()

# Calling the function
func()

Additional Notes:

  • Image Format Compatibility: Tkinter supports .png and .bmp formats for PhotoImage objects, and .ico for BitmapImage objects. If you're trying to use a different image format, you might need to convert it or load it using a different method.

  • Scope of icon: Ensure that the icon object is accessible when calling root.call('wm', 'iconphoto', root._w, icon). If icon is created inside the function, you need to ensure that it's in the correct scope. In your working example, icon might have been loaded outside the function, which made it available when the iconphoto method was called.

By ensuring the correct image format and making sure the icon variable is properly loaded before you use it, you should be able to resolve this issue.