I've written a Python 3 TkInter-based GUI application that launches a worker thread in the background. After the worker thread has finished, it waits two seconds (this is to avoid a possible race condition), and then sends a KeyboardInterrupt to tell the main thread it can close down.
Expected behaviour: running the program launches a GUI window, prints some text to the console after which the program closes down automatically.
Actual behaviour: instead of closing automatically, it only does so after the user either hovers the mouse over the GUI window area, or presses a key on the keyboard! Apart from that the program runs without reporting any errors.
Anyone have any idea why this is happening, and how to fix this? I already tried to wrap the KeyboardInterrupt into a separate function and then call that through a timer object, but this results in the same behaviour.
I've been able to reproduce this issue on 2 different Linux machines that run Python 3.5.2. and 3.6.6 respectively.
#! /usr/bin/env python3
import os
import threading
import _thread as thread
import time
import tkinter as tk
import tkinter.scrolledtext as ScrolledText
class myGUI(tk.Frame):
# This class defines the graphical user interface
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.root = parent
self.build_gui()
def build_gui(self):
# Build GUI
self.root.title('TEST')
self.root.option_add('*tearOff', 'FALSE')
self.grid(column=0, row=0, sticky='ew')
self.grid_columnconfigure(0, weight=1, uniform='a')
# Add text widget to display logging info
st = ScrolledText.ScrolledText(self, state='disabled')
st.configure(font='TkFixedFont')
st.grid(column=0, row=1, sticky='w', columnspan=4)
def worker():
"""Skeleton worker function, runs in separate thread (see below)"""
# Print some text to console
print("Working!")
# Wait 2 seconds to avoid race condition
time.sleep(2)
# This triggers a KeyboardInterrupt in the main thread
thread.interrupt_main()
def main():
try:
root = tk.Tk()
myGUI(root)
t1 = threading.Thread(target=worker, args=[])
t1.start()
root.mainloop()
t1.join()
except KeyboardInterrupt:
# Close program if subthread issues KeyboardInterrupt
os._exit(0)
main()
(Github Gist link to the above script here)