I'm trying to run a multi thread application,
each thread is asking for the user to provide a string input after some tasks the thread does.
simpledialog.askstring(title, content, parent=window)
the problem is that you cannot use the main thread window as the parent window inside a thread because you'll end up with this error:
_tkinter.TclError: window ".!_querystring2" was deleted before its visibility changed
which is logical because the thread and the main thread are not synchronized
after hard research I've ended up with a solution which says
"Create a new TK window instance for the thread"
newWin = tk.Tk()
newWin.withdraw() #to make it invisible
simpledialog.askstring(title, content, parent=newWin)
newWin.destroy()
which will work for my case if I wouldn't have a main tk window instance inside the main thread.
the destroy method for the "newWin" is causing my main window to be destroyed as well.
and I'll be ended up with this error :
Tcl_AsyncDelete: async handler deleted by the wrong thread
tkinter isn't a thread safe, and not gives an easy life when using it cross threads.
does anyone have any idea/trick how can I ask a string from a user inside a thread?
Some extra info about my code :
I'm triggering this function by a button click:
#tree is a treeview widget
def click(tree):
threads = simpledialog.askstring("Threads", "How many threads?")
if threads is not None:
try:
threads = int(threads)
if threads > 0:
thread = tm.threadObject(name="checkAccounts", target=checkUsers, args=[tree, threads])
thread.start()
#instance passes automatically from the tm.threadObject
def checkUsers(instance, tree, threads):
for child in tree.get_children():
while len(tm.threadsManager.getThreads("checkAccountWorker")) >= threads and instance.alive:
print("Sleeping")
time.sleep(1)
if not instance.alive:
break
item = tree.item(child)
taskHandler = task.taskHandler(tree, child)
thread = tm.threadObject(name="checkAccountWorker", target=taskHandler.doAction, args=[taskHandler.CHECK_USER], kill=taskHandler.kill, killargs=[], passInstance = False)
thread.start()
#part of the doAction code:
def doAction(*args):
#some code behind
newWin = tkinter.Tk()
newWin.withdraw()
code = tkinter.simpledialog.askstring("Activation", "Enter recevied code : ", parent=newWin)
newWin.destroy()
self.currentStatus = "Entering code"
mainEvents.updateTreeItem(tree, "status", item, self.currentStatus)
def updateTreeItem(tree, column, item, value):
key = ""
for col in tree["columns"]:
if tree.heading(col)["text"].lower() == column.lower():
key = col
if key == "":
return
tree.set(item, key, value)
It works at the first attempt. but when I click again on the checkUsers button I end up with the error :
"Tcl_AsyncDelete: async handler deleted by the wrong thread"
I honestly don't know why
question from:
https://stackoverflow.com/questions/65868995/tkinter-ask-a-string-inside-a-thread