Tkinter GUI Freezes - Tips to Unblock/Thread?
Question: New to python3 and started my first project of using a raspberry pi 3 to
create an interface to monitor and control elements in my greenhouse.
Currently the program reads Temperature and Humidity via a DHT11 sensor, and
controls a number of relays and servo via the GPIO pins.

I created a GUI to display the Temperature and Humidity that reads and updates
every 250ms. There is also a number of buttons that control the specific
relays/servo.

I am now running into some issues with the tkinter GUI freezing on a button
press. I have looked on the forum a bit but don't understand how to implement
threading or a check function to keep my GUI from freezing.

Code Below:

    
    
    from tkinter import *
    import tkinter.font
    import RPi.GPIO as GPIO
    import time
    import Adafruit_DHT
    
    #Logic Setup
    
    temp = 0
    humd = 0
    
    #GPIO Setup
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(16, GPIO.OUT) #Water Pump
    GPIO.setup(18, GPIO.IN)  #Tank Float Switch
    GPIO.output(16, GPIO.LOW)
    
    #Window Setup
    
    win = Tk()
    win.title("Test")
    win.geometry("200x300+0+0")
    
    #Label Setup
    
    Label (win, text="Temperature", fg="red", bg="black", font="24").grid(row=0, column=0)
    Label (win, text="Humidity", fg="red", bg="black", font="24").grid(row=0, column=2)
    Label (win, text="Water System", fg="red", bg="black", font="24").grid(row=3, column=0)
    
    TEMP = Label (win, text="", fg="black", bg="white", font="36")
    TEMP.grid(row=1, column=0)
    
    HUMD = Label (win, text="", fg="black", bg="white", font="36")
    HUMD.grid(row=1, column=2)
    
    #Functions
    
    def wait(time_lapse):
        time_start = time.time()
        time_end = (time_start+time_lapse)
    
        while time_end >= time.time():
            pass
    
    def RTEMP ():
        global temp
        humidity, temperature = Adafruit_DHT.read_retry(11, 27)
        temp = temperature * 9/5.0 + 32
        TEMP.configure(text=str(temp))
    
    def RHUMD ():
        global humd
        humidity, temperature = Adafruit_DHT.read_retry(11, 27)
        humd = humidity
        HUMD.configure(text=str(humd))        
    
    def READ ():
        RTEMP()
        RHUMD()
        win.after(250, READ)
    
    def PUMP ():
        if GPIO.input(18):
            WTR.config(bg="green")
            GPIO.output(16, GPIO.HIGH)
            wait (10)
            GPIO.output(16, GPIO.LOW)
            WTR.config(text="Water", bg="grey")
        else:
            GPIO.output(16, GPIO.LOW)
            WTR.config(text="LOW WATER", bg="red")
    
    #Buttons
    
    WTR = Button(win, text="Water", bg="grey", command = PUMP, height = 2, width = 8)
    WTR.grid(row=4, column=0) #Water Pump Control
    
    #Function Calls
    
    READ()
    
    mainloop()
    


Answer: Tkinter GUIs (as well as most other GUIs) are in a perpetual wait state.
There's no reason to introduce explicit waiting for events.

If you need to run some function, and then run some other function 10ms later,
you would schedule the other code to run with `after`. For example:

    
    
        GPIO.output(16, GPIO.HIGH)
        win.after(10, GPIO.output, 16, GPIO.LOW)
    

Naturally, if you want to do more than one thing you can use `lambda` or write
another function.

