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()