Search code examples
pythonuser-interfacetkinterlive

How to update Tkinter label when reading from a text file


I am new to python so I appreciate any help. I'm trying to build a gps speedometer and use Tkinter to make a gui to display the info. I'm having difficulty getting Tkinter to update the displayed text. For the current method (not shown in the code below), I have one script running and outputting 2 text files named "MPH.txt" and "Time.txt" with values such as "0.00" and "232445.500" respectively. This happens continuously and writes over the old files. Here is the code I have to read and display them. It will read it once and display the correct data, but I cant get it to update no matter what approach I take to forcing it to clear the text in each widget. I can close and open the window and it updates, but would like to start it and have it update on its own.

import serial
import tkinter as tk
import tkinter.font

win = tk.Tk()
win.title("GPS Speedometer")
win.geometry('1920x720')

i=1
while True:
        if i == 1:
                time_text=tk.Label(text="Current Time (UTC)").grid(row=0, col$
                with open("Time.txt", "r") as t:
                        tk.Label(win, text=t.read()).grid(row=1, column=0)
                        t.close()

                speed_text=tk.Label(text="Current Speed (Knots)").grid(row=2,$
                with open("MPH.txt", "r") as s:
                        tk.Label(win, text=s.read()).grid(row=3, column=0)
                        s.close()

                exitButton=tk.Button(win, text='exit', command=win.destroy).g$
                i=i-1
        else:
                i=i+1

        tk.mainloop()

Solution

  • You can't use a while or for loop in a GUI because it interferes with the GUI's mainloop. You have to add your code to the mainloop with the after method. Like this (plus a lot of other fixes):

    import tkinter as tk
    
    def loop():
        with open("Time.txt", "r") as t:
            time_text.config(text=t.read())
        with open("MPH.txt", "r") as s:
            speed_text.config(text=s.read())
        win.after(500, loop) # run every 500 milliseconds
    
    win = tk.Tk()
    win.title("GPS Speedometer")
    
    # using 2 lines per label is very important to make this work!
    lbl=tk.Label(text="Current Time (UTC)")
    lbl.grid(row=1, column=0)
    time_text = tk.Label(win, text='loading')
    time_text.grid(row=1, column=1)
    
    lbl=tk.Label(text="Current Speed (Knots)")
    lbl.grid(row=2,column=0)
    speed_text = tk.Label(win, text='loading')
    speed_text.grid(row=2, column=1)
    
    exitButton=tk.Button(win, text='exit', command=win.destroy)
    exitButton.grid()
    
    loop() # start your loop
    tk.mainloop() # start the mainloop