Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
The program below simply tests whether I can call root.destroy() of tkinter in a child thread. Though no error raised, I see a lot of posts in stackoverflow reminding people not to use tkinter in a child thread, so I wonder if calling root.destroy() in a child thread is not a good idea too, though I used tkinter in the main thread?
import tkinter
from tkinter import ttk
import time
import _thread
def callBackFunc():
global LOOP_ACTIVE
LOOP_ACTIVE = False
root = tkinter.Tk()
root.geometry('200x100')
chkValue = tkinter.BooleanVar()
chkValue.set(False)
chk = ttk.Checkbutton(root, variable=chkValue, text='Click me', command=callBackFunc)
chk.grid(column=0, row=0)
def loop_function():
global LOOP_ACTIVE
LOOP_ACTIVE = True
while LOOP_ACTIVE:
print(chk.state())
time.sleep(5)
print("you clicked me")
root.destroy()
_thread.start_new_thread(loop_function, ())
root.mainloop()
print("printed after mainloop ends")
–
–
You can avoid calling destroy()
in the child thread by periodically checking the flag in the main GUI thread by using the universal after()
widget method to schedule them to occur.
In the code below I've added a check_loop_status()
function that does that, and it will call root.destroy()
if it discovers that the LOOP_ACTIVE
flag is no longer set. To keep on process going, it schedules another call to itself before returning (which of course will never happen if destroy()
got called).
Since this all that happens in the main thread, any call to destroy()
will be fine.
import tkinter
from tkinter import ttk
import time
import _thread
DELAY = 1000 # milliseconds
root = tkinter.Tk()
root.geometry('200x100')
chkValue = tkinter.BooleanVar(value=False)
def callBackFunc():
global LOOP_ACTIVE
print("button was clicked")
LOOP_ACTIVE = False
def check_loop_status():
global LOOP_ACTIVE
if not LOOP_ACTIVE:
root.destroy() # OK in this function.
root.after(DELAY, check_loop_status) # Check again after delay.
chk = ttk.Checkbutton(root, variable=chkValue, text='Click me', command=callBackFunc)
chk.grid(column=0, row=0)
def loop_function():
global LOOP_ACTIVE
while LOOP_ACTIVE:
print(f'Checkbutton state: {chk.state()}')
time.sleep(5)
LOOP_ACTIVE = True
_thread.start_new_thread(loop_function, ())
check_loop_status() # Start periodic checking.
root.mainloop()
print("printed after mainloop ends")
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.