2

I've been trying for the past couple of hours to find a way to refresh a label with information without having to input anything myself.

The program I am trying to write is taking the CPU temp from the Raspberry Pi and displaying it in a window. I need to make that temp input to update every 5 seconds or so, but all attempts to do so have failed. I tried while loops and found that they do not work inside tkinter, and I can't think how to refresh something constantly without input without one. I am quite new to Python so I'm sure there is a way and I just haven't come across it yet. Similar questions on here don't quite lead to an answer that applies for me.

Here is my bit of code right now:

import subprocess
from tkinter import *

root = Tk()
root.title('CPU Temp')

cpuLab = Label(root, text = 'CPU Temp:',
               font =('Nimbus Mono L',14,),
               bg = 'black', fg = 'green').grid(row = 0, column = 0)

cpuTemp = subprocess.check_output(['/opt/vc/bin/vcgencmd', 'measure_temp'])

cpuVar = StringVar()
cpuDisplay = Label(root, textvariable = cpuVar,
                   font =('Nimbus Mono L',14),
                   bg = 'black', fg = 'green').grid(row = 0, column = 1)
cpuVar.set(cpuTemp[5:11])

root.mainloop()

This works perfectly for showing the temperature, it just has to be rerun in order to refresh.

Ben Wordy
  • 49
  • 1
  • 9

2 Answers2

5

Tkinter root windows have a method called after which can be used to schedule a function to be called after a given period of time. So call that function itself like (you will have to create a class first):

def update_label(self):
    self.label.configure(cpuTemp)
    self.root.after(1000, self.update_label)

This will then reload your label every second.

This may help you: Creating a Timer with tkinter

Community
  • 1
  • 1
frankenapps
  • 5,800
  • 6
  • 28
  • 69
  • 2
    Putting the GUI into a class is nice, but not strictly necessary. – PM 2Ring Apr 07 '16 at 16:29
  • thank you very much! I think didn't see that other post while searching due to the naming but combined with your answer looks like it perfectly answers my question. I did not notice `after` when looking through the tkinter documentation, but that's brilliant, thanks again! – Ben Wordy Apr 07 '16 at 16:35
  • No problem, glad i was able to help. – frankenapps Apr 07 '16 at 16:41
  • unfortunately, after getting through a fair few silly errors on my part, the script now runs without error but the label doesn't update with the information. I think it isn't rerunning the `subprocess.check_output` again it is just grabbing that same string it first generated continuously. I tried putting `cpuTemp =...` into `update_label` instead of `__init__ `where it was to try and loop it but that just gave me an AttributeError: cpuApp object has no attribute "cpuTemp"` – Ben Wordy Apr 07 '16 at 17:04
  • ok, I got it to work finally, I had to have `update = self.cpuTemp = subprocess.check_output(...)` within update_label as well as having the same thing, minus the `update =` in `__init__`. thanks again for the help! – Ben Wordy Apr 07 '16 at 17:45
0

TKINTER

Refresh, Update, Rerender

This code works for any type of Tkinter widget update

#!/usr/bin/env python3


import sys
import time
from tkinter import *

# Global variables
running = True


# Button action updater
def callback():
    if button_1["state"] == "disabled":
        button_1["state"] = "normal"
    else:
        button_1["state"] = "disabled"
        root.after(4000, callback)


# Window setup
root = Tk()
root.title("Buttons")
root.geometry("400x300")

# Buttons setup
button_1 = Button(root, text="Learn Python", command=callback)
button_1.pack()


# Software loop
root.mainloop()

Python version used to created this software is: >=3.x

victorkolis
  • 780
  • 13
  • 13
  • 1
    There's no need to call `update` in a loop, it's less efficient than calling tkinter's built-in `mainloop`. Also, you only need to call `root.protocol` once. Calling it in a loop has no benefit. – Bryan Oakley Dec 02 '21 at 04:27
  • There is problem with your code. Once you set the state to disabled, the callback won't be called again, so it's impossible to set it back to normal. The `if button_1["state"] == "disabled"` will never be true since the callback isn't called when the state is disabled. – Bryan Oakley Dec 27 '21 at 19:32
  • Wrong amigo, the code is using a recursive state. At some point the if statement resolves to True. Run on your machine and debug it. – victorkolis Dec 27 '21 at 19:59
  • Ok, yes, of course, I see now. You're calling it every four seconds via `after`. Sorry for not noticing that. – Bryan Oakley Dec 27 '21 at 21:37