Tkinter problems with GUI when entering while loop
Question: I have a simple GUI which run various scripts from another python file,
everything works fine until the GUI is running a function which includes a
while loop, at which point the GUI seems to crash and become in-active. Does
anybody have any ideas as to how this can be overcome, as I believe this is
something to do with the GUI being updated,Thanks. Below is a simplified
version of my GUI.

GUI

    
    
    #!/usr/bin/env python
    # Python 3
    
    from tkinter import *
    from tkinter import ttk
    from Entry import ConstrainedEntry
    import tkinter.messagebox
    import functions
    
    AlarmCode = "2222"
    
    root = Tk()
    root.title("Simple Interface")
    mainframe = ttk.Frame(root, padding="3 3 12 12")
    mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
    mainframe.columnconfigure(0, weight=1)
    mainframe.rowconfigure(0, weight=1)
    
    
    ttk.Button(mainframe, width=12,text="ButtonTest", 
               command=lambda: functions.test()).grid(
                 column=5, row=5, sticky=SE)
    
    for child in mainframe.winfo_children():
        child.grid_configure(padx=5, pady=5)
    
    root.mainloop()
    

functions

    
    
    def test():
        period = 0
        while True:
            if (period) <=100:
                time.sleep(1)
                period +=1
                print(period)
            else:
                print("100 seconds has passed")
                break
    

What will happen in the above is that when the loop is running the application
will crash. If I insert a break in the else statement after the period has
elapsed, everything will work fine. I want users to be able to click when in
loops as this GUI will run a number of different functions.


Answer: Don't use `time.sleep` in the same thread than your Tkinter code: it freezes
the GUI until the execution of `test` is finished. To avoid this, you should
use
[`after`](http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/universal.html)
widget method:

    
    
    # GUI
    ttk.Button(mainframe, width=12,text="ButtonTest", 
               command=lambda: functions.test(root))
               .grid(column=5, row=5, sticky=SE)
    
    # functions
    def test(root, period=0):
        if period <= 100:
            period += 1
            print(period)
            root.after(1000, lambda: test(root, period))
        else:
            print("100 seconds has passed")
    

* * *

**Update:**

In your comment you also add that your code won't use `time.sleep`, so your
original example may not be the most appropiate. In that case, you can create
a new thread to run your _intensive_ code.

Note that I posted the alternative of `after` first because multithreading
should be used only if it is completely necessary - it adds overhead to your
applicacion, as well as more difficulties to debug your code.

    
    
    from threading import Thread
    
    ttk.Button(mainframe, width=12,text="ButtonTest", 
               command=lambda: Thread(target=functions.test).start())
               .grid(column=5, row=5, sticky=SE)
    
    # functions
    def test():
        for x in range(100):
            time.sleep(1) # Simulate intense task (not real code!)
            print(x)
        print("100 seconds has passed")
    

