Home > Software engineering >  Pythong Tkinter freezing when updating label
Pythong Tkinter freezing when updating label

Time:05-25

I am trying to get a Tkinter window to change a label based on temperature probe readings. I have found some people who have done similar but my code doesn't seem to work. Instead the Tkinter window hangs. The code seems to continue looping and printing output to terminal, just Tkinter doesn't work.

Any ideas? I apologise for my poor code layout. I've only been learning python/coding for a few weeks.

from random import randint
import time
import tkinter as tk
import tkinter.font as tkfont


def tempprobe():
    while True:
        tempsimsum = 0
        for count in range(4):
            # This is to simulate temperature probe readings. 4 per second. Takes 4 readings then finishes loop
            tempsimraw = randint(14, 30)
            time.sleep(0.25)
            tempsimsum = tempsimsum   tempsimraw

        global temperature
        global temperatureWindow
        temperature.set(value=tempsimsum / 4)   # Averaging so lessen noise and spikes
        print(temperature.get())
        # This should 'refresh' labeltemperature in the tk window and restart this function but it just hangs the window
        temperatureWindow.after(500, tempprobe())


temperatureWindow = tk.Tk()

dfont = tkfont.Font(size=-24)

temperature = tk.DoubleVar()
labeltemperature = tk.Label(textvariable=temperature, font=dfont)
labeltemperature.pack()
buttonstart = tk.Button(text='Start',
                    font=dfont,
                    command=tempprobe)
buttonstart.pack()

temperatureWindow.mainloop()

CodePudding user response:

from random import randint
import time
import tkinter as tk
import tkinter.font as tkfont


def tempprobe():
    tempsimsum = 0
    for count in range(4):
        # This is to simulate temperature probe readings. 4 per second. Takes 4 readings then finishes loop
        tempsimraw = randint(14, 30)
        time.sleep(0.25)
        tempsimsum = tempsimsum   tempsimraw

    global temperature
    global temperatureWindow
    temperature.set(value=tempsimsum / 4)   # Averaging so lessen noise and spikes
    print(temperature.get())
    # This should 'refresh' labeltemperature in the tk window and restart this function but it just hangs the window
    temperatureWindow.after(500, tempprobe)


temperatureWindow = tk.Tk()

dfont = tkfont.Font(size=-24)

temperature = tk.DoubleVar()
labeltemperature = tk.Label(textvariable=temperature, font=dfont)
labeltemperature.pack()
buttonstart = tk.Button(text='Start',
                    font=dfont,
                    command=tempprobe)
buttonstart.pack()

temperatureWindow.mainloop()

CodePudding user response:

Don't use while because it blocks mainloop() and it can't get events from system, etc. and it can't redraw window - so it freezes.

You should use only after(10, tempprobe) to repeate it.

But after() needs function's name without () (like command= or bind())


Full code with other changes and only with my comments.

from random import randint
import time
import tkinter as tk

# --- functions ---

def tempprobe():
    # all `global` at the beginning of function
    #global temperature         # you don't need `global` if you don't use `=` to assign new value
    #global temperature_window  # you don't need `global` if you don't use `=` to assign new value
    
    tempsimsum = 0

    for count in range(4):
        tempsimraw = randint(14, 30)
        time.sleep(0.25)
        tempsimsum  = tempsimraw

    temperature.set(tempsimsum / 4)
    print(temperature.get())
    
    temperature_window.after(500, tempprobe)  # without `()`


# --- main ---

temperature_window = tk.Tk()  # PEP8: `lower_case_names` for variables

temperature = tk.DoubleVar(temperature_window)

# every widget should have `parent` as first value
label_temperature = tk.Label(temperature_window, textvariable=temperature)  
label_temperature.pack()

# every widget should have `parent` as first value
button_start = tk.Button(temperature_window, text='Start', command=tempprobe)
button_start.pack()

temperature_window.mainloop()

PEP 8 -- Style Guide for Python Code


But problem makes also sleep(0.25) which also blocks mainloop() and this need more complex change.

I would use list to keep values. If I would get 4 values then I could calculate temperature, clear list and make longer delay - 500ms. If I would have less values then I would add make shorter delay - 250ms.

from random import randint
import time
import tkinter as tk

# --- functions ---

last_values = []

def tempprobe():

    tempsimraw = randint(14, 30)
    last_values.append(tempsimraw)

    if len(last_values) == 4:
        tempsimsum = sum(last_values)
        temperature.set(tempsimsum / 4)
        print(temperature.get())

        last_values.clear()  # remove all values
        
        temperature_window.after(500, tempprobe)
    else:
        temperature_window.after(250, tempprobe)


# --- main ---

temperature_window = tk.Tk()  # PEP8: `lower_case_names` for variables

temperature = tk.DoubleVar(temperature_window)

# every widget should have `parent` as first value
label_temperature = tk.Label(temperature_window, textvariable=temperature)  
label_temperature.pack()

# every widget should have `parent` as first value
button_start = tk.Button(temperature_window, text='Start', command=tempprobe)
button_start.pack()

temperature_window.mainloop()
  • Related