1

I was wondering if there was a way to run the tkinter mainloop on a separate thread (not the mainthread) so that the terminal is "free".

Let's say we have a simple GUI:

import tkinter as tk       

class Application(tk.Frame):              
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)   
        self.grid()                       
        self.createWidgets()

    def printHello(self):
        print("Hello")

    def createWidgets(self):
        self.quitButton = tk.Button(self, text='Quit',
            command=self.quit)            
        self.quitButton.grid(row=1,column=0)    
        self.printButton = tk.Button(self, text='Print',command=lambda: self.printHello())         
        self.printButton.grid(row=1,column=1) 
app = Application()                        
app.master.title('Sample application')     
app.mainloop()

Observed behavior: if I run this file using the terminal in PyCharm (let's say) using: python application.py, the terminal is then "frozen"/"occupied" by the tkinter mainloop and I am not able to type anything in the terminal.

Desired behavior: if I run the gui file with python application.py, the terminal is "free" such that it is able to take in additional commands.

I'm aware that python application.py & is supposed to free up the terminal but that hasn't worked for me. I'm not very experienced with threading or GUI processes but is there a way to run the tkinter mainloop in a different process / thread so that the terminal will be "free"?

2
  • Try using pythonw: pythonw application.py Commented Oct 13, 2020 at 5:07
  • but is there a way to manually implement the threading? Commented Oct 13, 2020 at 5:12

1 Answer 1

3

You can use the threading module to run the GUI in a background thread while using the terminal in the main thread.

Try this code. It will start the GUI then allow input from the terminal.

import tkinter as tk       
import threading

class Application(tk.Frame):              
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)   
        self.grid()                       
        self.createWidgets()

    def printHello(self):
        print("Hello")

    def createWidgets(self):
        self.quitButton = tk.Button(self, text='Quit',
            command=self.quit) # exits background (gui) thread
        self.quitButton.grid(row=1,column=0)    
        self.printButton = tk.Button(self, text='Print',command=lambda: self.printHello())         
        self.printButton.grid(row=1,column=1) 

def runtk():  # runs in background thread
    app = Application()                        
    app.master.title('Sample application')     
    app.mainloop()
    
thd = threading.Thread(target=runtk)   # gui thread
thd.daemon = True  # background thread will exit if main thread exits
thd.start()  # start tk loop

while True:  # run in main thread
   x = input("Enter a value or Q to quit: ")
   if x.lower() == 'q':
      exit()
   print('You entered', x)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.