Search code examples
pythontkintertk-toolkit

Python tKinter hanging


Why does in the code below button1 hang until the time.sleep(10) has completed.

I can only assume tKinter is waiting for the click event to finish before updating it's paint function.

I want on button1 click the state to change to DISABLED as in the code straight away, not when mainformbutton1press() has finished.

I have put time.sleep(10) to mimic rest of code functions - but the actual programme will be many minutes instead.

EDIT! - sleep is just there to show how tkinter hangs. My real programme has lots more code and no sleep function - and it takes a long time to process data with the hung GUI as mentioned. No more sleep suggestions please :)

import tkinter as tk
from tkinter import ttk
from tkinter.constants import DISABLED, NORMAL
import time

# ==================================================
class App:

    def __init__(self, tk, my_w):
  
        self.button1 = tk.Button(my_w, text="START", width=34, command = self.mainformbutton1press)
        self.button1.grid(columnspan=3, row=6, column=1,padx=10,pady=20, ipadx=20, ipady=20)        

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def mainformbutton1press(self):
  
        self.button1.config(text="PLEASE WAIT...")
        self.button1['state'] = DISABLED
     
        # DO REST OF PROCESSING
        # TO MIMIC THIS:
        time.sleep(10)
        print("doing...")
     
# ==================================================
if __name__ == "__main__":
   
    my_w = tk.Tk()
    my_w.geometry("430x380")
    my_w.resizable(False, False)
    
    app = App(tk, my_w)

    my_w.mainloop()  # Keep the window open

Solution

  • Tk.mainloop is a sort of while loop. time.sleep() stops the loop for a particular period of time. That makes the window unresponsive. You might use .after function:

    class App:
    
        def __init__(self, tk, my_w):
            self.my_w=my_w
            ....
        def continue_next(self):
            print("Doing")
            ....
        def mainformbutton1press(self):
      
            self.button1.config(text="PLEASE WAIT...")
            self.button1['state'] = DISABLED
         
            # DO REST OF PROCESSING
            # TO MIMIC THIS:
            self.my_w.after(10000,self.continue_next)