CustomTkinter
CustomTkinter copied to clipboard
CTkImage on setting inside a label throws (_tkinter.TclError: image "pyimage4" doesn't exist) error
I am working on pycharm so the error is not Spyder specific as some were saying on stackoverflow. i tries runnign the program on the global system terminal still the same error.
Code
class EyeButton:
def __init__(self, master: customtkinter.CTkEntry, hide_char: str):
self.master = master
self.hide_char = hide_char
self.unhide = customtkinter.CTkImage(dark_image=Image.open("Eye.png"), size=(22, 18))
self.hide = customtkinter.CTkImage(dark_image=Image.open("NotEye.png"), size=(24, 20))
self.buttonLabel = customtkinter.CTkLabel(master=self.master, font=('Roboto', 12), text='', image=self.unhide, fg_color='transparent', height=self.master.winfo_height()-10) # Traces back error to this line while defining the image self.unhide
def initialize(self):
self.buttonLabel.bind("<Button-1>", lambda e: self.state())
self.buttonLabel.place(relx=0.99, rely=0.5, anchor='e')
self.tracker = 1
def state(self):
if self.tracker == 1:
self.master.configure(show="")
self.buttonLabel.configure(image=self.hide)
self.tracker = False
else:
self.master.configure(show=self.hide_char)
self.buttonLabel.configure(image=self.unhide)
self.tracker = True
self.tracker *= 1
def login_box():
ConnectionWin.after(200, lambda: threading.Thread(target=ConnectionWin.destroy).start())
box = customtkinter.CTk()
box.title("PyChat Login")
box.iconbitmap('PyChat.ico')
w = 400
h = 410
box.geometry(get_geo(box, w, h))
frame = customtkinter.CTkFrame(master=box)
frame.pack(pady=20, padx=40, fill="both", expand=True)
uname = customtkinter.CTkEntry(master=frame, placeholder_text="Username", width=240)
uname.pack(pady=12, padx=10)
passwd = customtkinter.CTkEntry(master=frame, placeholder_text="Password", show="•", width=240)
passwd.pack(pady=12, padx=10)
box.update()
showButton = EyeButton(master=passwd, hide_char="•") #Getting error while creating child
showButton.initialize()
LoginButton = customtkinter.CTkButton(master=frame, text="Sign in", command=login)
LoginButton.pack(pady=12, padx=10)
box.update()
box.mainloop()
The class is used to create a eye button that hides and unhides password inside the CTkEntry box. Previously it used to work fine unless i added a loading screen before the login screen that gets destroyed inside the login_box function via a thread (the ConnectionWin) but since the button is initilized before the window gets destroyed it trows the following error.
Error
Traceback (most recent call last):
File "C:\Users\Rishi\PycharmProjects\PyChat\test.py", line 253, in connect
login_box()
File "C:\Users\Rishi\PycharmProjects\PyChat\test.py", line 180, in login_box
showButton = EyeButton(master=passwd, hide_char="•")
File "C:\Users\Rishi\PycharmProjects\PyChat\test.py", line 16, in __init__
self.buttonLabel = customtkinter.CTkLabel(master=self.master, font=('Roboto', 12), text='', image=self.unhide, fg_color='transparent', height=self.master.winfo_height()-10)
File "C:\Users\Rishi\PycharmProjects\PyChat\venv\lib\site-packages\customtkinter\windows\widgets\ctk_label.py", line 93, in __init__
self._update_image()
File "C:\Users\Rishi\PycharmProjects\PyChat\venv\lib\site-packages\customtkinter\windows\widgets\ctk_label.py", line 130, in _update_image
self._label.configure(image=self._image.create_scaled_photo_image(self._get_widget_scaling(),
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 1675, in configure
return self._configure('configure', cnf, kw)
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 1665, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: image "pyimage4" doesn't exist
I tried decreasing the after() time for destroying the window but that results in another RuntimError mainthread is not inside mainloop and i also tried to disable the garbage collector so that it doesnt collect the vraible data and clear it by doing g.disable() and checked the gc state by gc.isenabled() which returned false but still the same error.
Code to replicate the error
Use a basic server to accept the connection to initiate the login window
import time
import traceback
import PIL.ImageTk
from PIL import Image
import tkinter as tk
import threading
import customtkinter
import socket as sock
class EyeButton:
def __init__(self, master: customtkinter.CTkEntry, hide_char: str):
self.master = master
self.hide_char = hide_char
self.unhide = customtkinter.CTkImage(dark_image=Image.open("Eye.png"), size=(22, 18))
self.hide = customtkinter.CTkImage(dark_image=Image.open("NotEye.png"), size=(24, 20))
self.buttonLabel = customtkinter.CTkLabel(master=self.master, text='', image=self.unhide, fg_color='transparent', height=self.master.winfo_height()-10)
self.buttonLabel.image = self.unhide
def initialize(self):
self.buttonLabel.bind("<Button-1>", lambda e: self.state())
self.buttonLabel.place(relx=0.99, rely=0.5, anchor='e')
self.tracker = 1
def state(self):
if self.tracker == 1:
self.master.configure(show="")
self.buttonLabel.configure(image=self.hide)
self.tracker = False
else:
self.master.configure(show=self.hide_char)
self.buttonLabel.configure(image=self.unhide)
self.tracker = True
self.tracker *= 1
class HyperLabel(customtkinter.CTkLabel):
def __init__(self, *args, **kwargs):
customtkinter.CTkLabel.__init__(self, *args, **kwargs)
self.bind('<Enter>', lambda e: self.on_hover())
self.bind('<Leave>', lambda e: self.on_leave())
def on_hover(self):
self.configure(text_color="#54a2de", font=('Roboto', 12, 'underline'))
def on_leave(self):
self.configure(text_color="#1f6aa5", font=('Roboto', 12))
class HyperImage(customtkinter.CTkLabel):
def __init__(self, on: customtkinter.CTkImage, off: customtkinter.CTkImage, *args, **kwargs):
self.on = on
self.off = off
customtkinter.CTkLabel.__init__(self, *args, **kwargs, image=off)
self.bind('<Enter>', lambda e: self.on_hover())
self.bind('<Leave>', lambda e: self.on_leave())
def on_hover(self):
self.configure(image=self.on)
def on_leave(self):
self.configure(image=self.off)
def get_geo(master, width, height):
screen_width = master.winfo_screenwidth()
screen_height = master.winfo_screenheight()
x = (screen_width / 2) - (width / 2)
y = (screen_height / 2) - (height / 2)
position = '%dx%d+%d+%d' % (width, height, x, y)
return position
def login_box():
ConnectionWin.after(200, lambda: threading.Thread(target=ConnectionWin.destroy).start())
box = customtkinter.CTk()
box.title("PyChat Login")
box.iconbitmap('PyChat.ico')
w = 400
h = 410
box.geometry(get_geo(box, w, h))
box.minsize(w, h)
box.maxsize(w, h)
frame = customtkinter.CTkFrame(master=box)
frame.pack(pady=20, padx=40, fill="both", expand=True)
label = customtkinter.CTkLabel(master=frame, text="Login", font=("Roboto", 24))
label.pack(pady=(12, 26), padx=10)
warning = customtkinter.CTkLabel(master=frame, text="", font=("Roboto", 12), text_color="#d94b58")
warning.pack(pady=0, padx=0)
warning.place(anchor='w', relx=0.135, rely=0.18)
uname = customtkinter.CTkEntry(master=frame, placeholder_text="Username", width=240)
uname.pack(pady=12, padx=10)
passwd = customtkinter.CTkEntry(master=frame, placeholder_text="Password", show="•", width=240)
passwd.pack(pady=12, padx=10)
box.update()
time.sleep(0.2)
showButton = EyeButton(master=passwd, hide_char="•")
showButton.initialize()
LoginButton = customtkinter.CTkButton(master=frame, text="Sign in", command=login)
LoginButton.pack(pady=12, padx=10)
remember = customtkinter.CTkCheckBox(master=frame, text="Stay Logged In")
remember.pack(pady=12, padx=10)
text = customtkinter.CTkLabel(master=frame, text="New to Pychat?", text_color="silver", font=('Roboto', 12))
signup = HyperLabel(master=frame, text="Sign up", text_color="#1f6aa5", font=('Roboto', 12))
signup.bind("<Button-1>", lambda e: register())
text.pack(pady=8, padx=2)
signup.pack(pady=8, padx=2)
box.update()
box.mainloop()
def splash():
global SplashWin
SplashWin = customtkinter.CTk()
SplashWin.overrideredirect(True)
w = 350
h = 180
SplashWin.geometry(get_geo(SplashWin, w, h))
icon = customtkinter.CTkImage(dark_image=Image.open("PyChat.png"), size=(98, 98))
logo = customtkinter.CTkLabel(master=SplashWin, text="", image=icon)
logo.place(anchor='center', relx=0.3, rely=0.36)
label = customtkinter.CTkLabel(master=SplashWin, text="PyChat", font=('Roboto', 40))
label.pack(pady=0, padx=0)
label.place(anchor='w', relx=0.45, rely=0.36)
loading = customtkinter.CTkLabel(master=SplashWin, text="Loading...", font=('Roboto', 16), text_color='silver')
loading.place(relx=0.5, rely=0.7, anchor='center')
loadbar = customtkinter.CTkProgressBar(master=SplashWin, corner_radius=0, width=350, border_width=0, fg_color='#1f6aa5', progress_color='#54a2de', indeterminate_speed=1.2)
loadbar.pack(side=tk.BOTTOM, pady=0, padx=0)
loadbar.configure(mode="indeterminnate")
loadbar.start()
SplashWin.after(4000, connect)
SplashWin.mainloop()
def fail_box():
ConnectionWin.after(500, lambda: threading.Thread(target=ConnectionWin.destroy).start())
global popup
popup = customtkinter.CTk()
popup.title("PyChat Connection Error")
popup.iconbitmap('PyChat.ico')
w = 400
h = 240
popup.geometry(get_geo(popup, w, h))
popup.minsize(w, h)
popup.maxsize(w, h)
frame = customtkinter.CTkFrame(master=popup)
frame.pack(pady=20, padx=40, fill="both", expand=True)
label = customtkinter.CTkLabel(master=frame, text="Connection Failed!", font=('Roboto', 28))
label.pack(padx=20, pady=20)
error = customtkinter.CTkLabel(master=frame, text="Unable to Connect to Server\nPlease try again later.", text_color='silver', font=('Roboto', 14))
error.pack(padx=20, pady=10)
button = customtkinter.CTkButton(master=frame, text="OK", width=70, command=lambda: popup.destroy())
button.pack(padx=20, pady=20)
popup.mainloop()
def connect():
SplashWin.destroy()
global client
th = threading.Thread(target=connect_box)
th.daemon = True
th.start()
client = sock.socket(sock.AF_INET, sock.SOCK_STREAM)
time.sleep(3)
try:
client.connect(('127.0.0.1', 5574))
loadbar1.stop()
ConnectionWin.withdraw()
login_box()
except ConnectionRefusedError:
loadbar1.stop()
ConnectionWin.withdraw()
fail_box()
except ConnectionError:
loadbar1.stop()
ConnectionWin.withdraw()
fail_box()
except Exception:
print(traceback.format_exc())
exit()
def connect_box():
global ConnectionWin, loadbar1
ConnectionWin = customtkinter.CTk()
ConnectionWin.title("PyChat")
ConnectionWin.iconbitmap('PyChat.ico')
w = 400
h = 370
screen_width = ConnectionWin.winfo_screenwidth()
screen_height = ConnectionWin.winfo_screenheight()
x = (screen_width / 2) - (w / 2)
y = (screen_height / 2) - (h / 2)
position = '%dx%d+%d+%d' % (w, h, x, y)
ConnectionWin.geometry(position)
ConnectionWin.minsize(w, h)
ConnectionWin.maxsize(w, h)
icon = customtkinter.CTkImage(dark_image=Image.open("PyChat.png"), size=(98, 98))
logo = customtkinter.CTkLabel(master=ConnectionWin, text="", image=icon)
logo.place(anchor='center', relx=0.3, rely=0.14)
label = customtkinter.CTkLabel(master=ConnectionWin, text="PyChat", font=('Roboto', 40))
label.pack(pady=0, padx=0)
label.place(anchor='w', relx=0.45, rely=0.14)
frame = customtkinter.CTkFrame(master=ConnectionWin)
frame.pack(pady=(100, 20), padx=40, fill="both", expand=True)
label = customtkinter.CTkLabel(master=frame, text="Connecting to server...", font=('Roboto', 24))
label.pack(padx=40, pady=40)
loadbar1 = customtkinter.CTkProgressBar(master=frame, corner_radius=20, width=240, progress_color='#54a2de', indeterminate_speed=0.8)
loadbar1.pack(pady=0, padx=0)
loadbar1.configure(mode="indeterminnate")
loadbar1.start()
Github = customtkinter.CTkImage(dark_image=Image.open("master/sources/github.png"), size=(124, 64))
GithubHighlight = customtkinter.CTkImage(dark_image=Image.open("master/sources/github_highlight.png"), size=(124, 64))
GitLabel = HyperImage(master=ConnectionWin, text="", width=24, height=30, cursor="hand2", on=GithubHighlight, off=Github)
GitLabel.bind("<Button-1>", lambda e: print('https://github.com/TriDEntApollO?tab=repositories'))
GitLabel.pack(pady=0, padx=20)
developed = customtkinter.CTkLabel(master=ConnectionWin, text="Developed by TriDEntApollO", text_color="silver")
developed.pack(pady=(0, 20), padx=20)
ConnectionWin.mainloop()
return
customtkinter.set_appearance_mode("Dark")
customtkinter.set_default_color_theme("dark-blue")
splash()
Server code to accept the connection
import socket as sock
server = sock.socket(sock.AF_INET, sock.SOCK_STREAM)
name = sock.gethostname()
host, port = sock.gethostbyname(name), 5574
server.bind((host, port))
server.listen(1)
client, address = server.accept()
I am having the same error while running the code on a Jupyter Notebook, it works fine on a normal .py file. Any solution?
I still haven't found any fix to the issue but i have seen this issue mostly occurs on Spyder or Jupiter notebook it's something with the ide/editor using their own shell rather use the global system shell/terminal
This probably won't be of much help but you can try also the issue is raised only when a previous window was created but not destroyed so you could try destroying the previous window first as tkinter only allows one root window at a time.
On Mon, 2 Jan 2023, 2:47 pm Swastik Kulshreshtha, @.***> wrote:
I am having the same error while running the code on a Jupyter Notebook, it works fine on a normal .py file. Any solution?
— Reply to this email directly, view it on GitHub https://github.com/TomSchimansky/CustomTkinter/issues/822#issuecomment-1368767908, or unsubscribe https://github.com/notifications/unsubscribe-auth/AQHGKDHYUJ7COCZTWOSARPLWQKMJTANCNFSM6AAAAAAS2KDJAE . You are receiving this because you authored the thread.Message ID: @.***>