Why is my label not updating variable from different function? Tkinter - python

I am writing a time clock program. I have built the code, but have had trouble creating a GUI around it. I have entries that takes input and sends them to an outside function with a button event handling for calculation.
Running the program, I do not get a label updating the time. I wonder if it has to do with my textvariables.
from tkinter import *
import time
import os
def show_entry_fields():
hr= hrvar.get()
mn = minvar.get()
sc = secvar.get()
counter = int(hr)*3600+int(mn)*60+ int(sc)
mins = int(counter/60)
hours = int(mins/60)
hours = IntVar()
mins = IntVar()
secs = IntVar()
while counter > 0:
counter -= 1
hours, sec = divmod(counter, 3600)
mins, sec = divmod(sec, 60)
printv = StringVar()
printv = (" %d Hr:, %d Min: %d Sec" % (hours, mins, sec))
win1 = Tk()
timeLabel = Label(win1, textvariable= printv).grid(row=7)
mins= int(counter/60)
hours = int(mins/60)
time.sleep(1)
os.system('cls')
return
else:
finishedLabel = Label(master, text="Time is Up").grid(row=7)
return
master = Tk()
Label(master, text="Enter Hour(s)").grid(row=0)
Label(master, text="Enter Mins(s)").grid(row=1)
Label(master, text="Enter Second(s)").grid(row=2)
hrvar = IntVar()
minvar = IntVar()
secvar = IntVar()
e1 = Entry(master, textvariable = hrvar)
e2 = Entry(master, textvariable = minvar)
e3 = Entry(master, textvariable = secvar)
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
e3.grid(row=2, column=1)
Button(master, text='Quit', command=master.quit).grid(row=3, column=0,
sticky=W, pady=4)
Button(master, text='Show', command=show_entry_fields).grid(row=3,
column=1,
sticky=W, pady=4)
mainloop( )
Updated code.
class Timer:
def __init__(self, master):
#self.seconds = 0
self.time = StringVar()
self.hr = StringVar()
self.mins = StringVar()
self.secs = StringVar()
self.hr_label = Label(master, text='Enter Hours').pack()
self.entry_hr = Entry(master, textvariable = self.hr )
self.entry_hr.pack()
self.min_label = Label(master, text='Enter Minutes').pack()
self.entry_min = Entry(master, textvariable = self.mins)
self.entry_min.pack()
self.time_label = Label(master, relief='flat', font=("Cambria", 20),
textvariable=self.time)
self.set_time(hours= self.entry_hr.get(), minutes=self.entry_min.get(), seconds = 0)
self.time.set('00:00:00')
self.start_button = Button(master, text='Start')
self.start_button.bind('<Button-1>', self.start_countdown)
self.time_label.pack(padx=30, pady=10)
self.start_button.pack(pady=(10,20))
def set_time(self, hours, minutes, seconds):
self.seconds = hours * 3600 + minutes * 60 + seconds
self.time.set(self.format_time(self.seconds))
def start_countdown(self, event):
self.countdown()
def countdown(self):
if self.seconds <= 0:
return
self.seconds -= 1
self.time.set(self.format_time(self.seconds))
self.time_label.after(1000, self.countdown)
def format_time(self, seconds):
h = seconds // 3600
m = (seconds - h*3600) // 60
s = seconds - h*3600 - m*60
return '{:0>2}:{:0>2}:{:0>2}'.format(h,m,s)
if __name__ == '__main__':
root = Tk()
timer = Timer(root)
#timer.set_time(hours=0, minutes=20, seconds=0)
root.mainloop()

There are several problems with your code. You are redefining printv, timeLabel, and creating a new Tk() object at every step in your while loop. More importantly, you define printv as a StringVar, but immediately redefine it as a string. You should define each of them once outside of the while loop and then use the set() method of printv.
Here is a very basic timer in Tkinter. First of all, you should not be using time.sleep or while loops. The mainloop function is already a while loop, and most tkinter objects have a .after() method that allows you to call events after a window of time (in milliseconds).
Notice that I created a class to encapsulate my entire UI. All variables are stored within the class and updated from its methods. The time is set within the script itself (currently to 1 hour, 20 minutes, 10 seconds), though that is easy to modify to accept args from the command line or from text fields in the UI.
from tkinter import Tk, Label, StringVar
from tkinter.ttk import Button, Entry
class Timer:
def __init__(self, master):
self.seconds = 0
self.time = StringVar()
self.time_label = Label(master, relief='flat', font=("Cambria", 20),
textvariable=self.time)
self.hr = StringVar()
self.hr_label = Label(master, text='Hours:').grid(row=1, column=1, padx=5, pady=1)
self.entry_hr = Entry(master, textvariable=self.hr, width=4)
self.entry_hr.grid(row=1, column=2)
self.mins = StringVar()
self.min_label = Label(master, text='Minutes:').grid(row=2, column=1, padx=5, pady=1)
self.entry_min = Entry(master, textvariable=self.mins, width=4)
self.entry_min.grid(row=2, column=2)
self.secs = StringVar()
self.secs_label = Label(master, text='Seconds:').grid(row=3, column=1, padx=5, pady=1)
self.entry_sec = Entry(master, textvariable=self.secs, width=4)
self.entry_sec.grid(row=3, column=2)
self.time.set('00:00:00')
self.start_button = Button(master, text='Start')
self.start_button.bind('<Button-1>', self.start_countdown)
self.time_label.grid(row=0, columnspan=4, padx=30, pady=10)
self.start_button.grid(row=4, columnspan=4, pady=(10,20))
def set_time(self, hours, minutes, seconds):
self.seconds = hours * 3600 + minutes * 60 + seconds
self.time.set(self.format_time(self.seconds))
def start_countdown(self, event):
h = self.entry_hr.get()
m = self.entry_min.get()
s = self.entry_sec.get()
h,m,s = map(lambda x: int(x) if x else 0, (h,m,s))
self.set_time(h,m,s)
self.countdown()
def countdown(self):
if self.seconds <= 0:
return
self.time.set(self.format_time(self.seconds))
self.seconds -= 1
self.time_label.after(1000, self.countdown)
def format_time(self, seconds):
h = seconds // 3600
m = (seconds - h*3600) // 60
s = seconds - h*3600 - m*60
return '{:0>2}:{:0>2}:{:0>2}'.format(h,m,s)
if __name__ == '__main__':
root = Tk()
timer = Timer(root)
root.mainloop()

Related

TKinter GUI freezing with root.after

I'm trying to create code to incrementally increase the voltage on a DC power supply over the span of an input duration. I've set up a GUI for doing this (it's my first try making a GUI, sorry if the code is weird), and everything works ... except that the GUI freezes while the code is executing so I can't stop the loop. I've looked into this for several hours and learned to use root.after instead of time.sleep, but it doesn't seem to have helped in the HeatLoop function. The GUI updates now, but only sporadically and there's still the "wait cursor" showing up when I mouse over the GUI. Is there some way to fix this?
I modified the code I'm using below so it should work on any computer without needing to be edited.
import datetime
import time
from tkinter import *
class GUIClass:
def __init__(self, root):
"""Initialize the GUI"""
self.root = root
self.percent = StringVar()
self.percent.set("00.00 %")
self.error = StringVar()
self.STOP = False
self.error.set("---")
self.currentvoltage = StringVar()
self.currentvoltage.set("Current Voltage: 00.00 V")
self.DT = datetime.datetime
# Create and attach labels
label1 = Label(root, text='Voltage')
label2 = Label(root, text='Ramp Duration')
label3 = Label(root, text='Percent Done: ')
label4 = Label(root, textvariable=self.percent)
label5 = Label(root, text="Error Message: ")
label6 = Label(root, textvariable=self.error)
label7 = Label(root, textvariable=self.currentvoltage)
label1.grid(row=0, column=0, sticky=W)
label2.grid(row=1, column=0, sticky=W)
label3.grid(row=2, column=0, sticky=W)
label4.grid(row=2, column=1, sticky=W)
label5.grid(row=3, column=0, sticky=W)
label6.grid(row=3, column=1, sticky=W)
label7.grid(row=3, column=2, sticky=E)
# Create and attach entries
self.voltage = Entry(root)
self.duration = Entry(root)
self.voltage.grid(row=0, column=1)
self.duration.grid(row=1, column=1)
# Create, bind, and attach buttons
HeatButton = Button(root, text='Heat')
HeatButton.bind("<Button-1>", self.Heat)
HeatButton.grid(row=0, column=2)
CoolButton = Button(root, text='Cool')
CoolButton.bind("<Button-1>", self.Heat)
CoolButton.grid(row=1, column=2)
StopButton = Button(root, text='Stop')
StopButton.bind("<Button-1>", self.Stop)
StopButton.grid(row=2, column=2)
def HeatLoop(self, condition, TimeStart, TimeDuration, MaximumVoltage, Fraction=0):
"""Heat up the cell while the condition is true"""
if condition:
self.percent.set("{:2.2f}%".format(Fraction * 100))
print(MaximumVoltage)
self.currentvoltage.set("Current Voltage: {:2.2f} V".format(Fraction*MaximumVoltage))
self.Update()
CurrentTime = self.DT.now()
ElapsedTime = (CurrentTime.second/3600 + CurrentTime.minute/60 + CurrentTime.hour
- TimeStart.second/3600 - TimeStart.minute/60 - TimeStart.hour)
Fraction = ElapsedTime / TimeDuration
print(Fraction)
self.root.after(5000)
self.HeatLoop(bool(not self.STOP and Fraction < 1),
TimeStart, TimeDuration, MaximumVoltage, Fraction)
# Define function to heat up cell
def Heat(self, event):
# Initialize Parameters
self.STOP = False
self.error.set("---")
self.Update()
# Try to get voltage and duration from the GUI
MaxVoltage = self.voltage.get()
TimeDuration = self.duration.get()
try:
MaxVoltage = float(MaxVoltage)
try:
TimeDuration = float(TimeDuration)
except:
self.error.set("Please enter a valid time duration")
self.Update()
self.STOP = True
except:
self.error.set("Please enter a valid voltage value")
self.Update()
self.STOP = True
TimeStart = self.DT.now()
self.HeatLoop(True,
TimeStart, TimeDuration, MaxVoltage)
def Stop(self, event):
self.STOP = True
print("turned off voltage")
def Update(self):
self.root.update_idletasks()
self.root.update()
root1 = Tk()
a = GUIClass(root1)
root1.mainloop()
root.after(5000) is no different than time.sleep(5). It's doing exactly what you're telling it to: to freeze for five seconds.
If you want to run self.HeatLoop every five seconds, the way to do it is like this:
self.root.after(5000, self.HeatLoop,
bool(not self.STOP and Fraction < 1),
TimeStart, TimeDuration, MaximumVoltage,
Fraction)
When you give two or more arguments to after, tkinter will add that function to a queue, and will call that function after the time has expired. This allows the event loop to continue to process events during the five second interval.
A slightly better way to write it would be to check for the condition inside the function rather than passing the condition in, so that the condition is evaluated immediately before doing the work rather than five seconds before doing the work.
For example:
def HeatLoop(self, TimeStart, TimeDuration, MaximumVoltage, Fraction=0):
if self.STOP and Fraction < 0:
return
...
self.root.after(5000, self.HeatLoop,
TimeStart, TimeDuration, MaximumVoltage,
Fraction)

Increasing integers at specific time with elapsed time

I'm trying to make a program that will work as an "infomercial" in a separate window.
What i have are two integers (x and y) that both increase at the same time, in this case every 5 seconds. With the increasing values i need a timer displayed at the same time, that can show the elapsed time of how long the program has been running. I want to be albe to start and pause the program
So far i have an infinite while loop running where the values are increased every 5 seconds with time.sleep(5). I have tried implementing a timer in the form of a time.time(), and get it to work with the increments. I have also added buttons but don't work. I'm using tkinter as gui obtion.
How am i supposed to make it work? with threading?
import time
from tkinter import *
import math
usage = 0
yearly = 0
cubik = 0
price = 0
root = Tk()
root.title("Usage of fluid")
root.geometry("300x400")
var = IntVar()
var1 = IntVar()
var2 = StringVar()
var3 = StringVar()
var4 = StringVar()
def update_timeText():
current= time.strftime("%H:%M:%S")
timeText.configure(text=current)
root.after(1000, update_timeText)
def start():
global state
state = True
def pause():
global state
state = False
def exist():
root.destroy()
frame = LabelFrame(root, text="Liter", font=30)
frame.pack(fill = "both", expand="yes")
l = Label(frame, textvariable=var, font=20)
l.pack(pady = 3)
frame2 = LabelFrame(root, text="price from use", font=30)
frame2.pack(fill = "both", expand= "yes")
l2 = Label(frame2, textvariable=var1, font=16)
l2.pack(side = LEFT)
l3 = Label(frame2, text="dollars", font=16)
l3.pack(side=LEFT)
frame3 = LabelFrame(root, text="yearly", font=30)
frame3.pack(fill = "both", expand="yes")
m3 = Label(frame3, textvariable=var2, font=16, wraplength=0)
m3.pack(side=TOP)
l4 = Label(frame3, text="Liter", font=16)
l4.pack(side=TOP)
l5 = Label(frame3, text="m3", font=16)
l5.pack(side=BOTTOM, fill="both")
m4 = Label(frame3, textvariable=var3, font=16, wraplength=0)
m4.pack(side=BOTTOM)
frame4 = LabelFrame(root, text='runtime', font=30)
frame4.pack(fill = "both", expand="yes")
timeText= Label(frame4, text="", font=16)
timeText.pack()
startButton = Button(frame4, text='Start', command=start)
startButton.pack()
pauseButton = Button(frame4, text='Pause', command=pause)
pauseButton.pack()
quitButton = Button(frame4, text='Quit', command=quit)
quitButton.pack()
while True:
var.set(usage)
usage += 300
var1.set(round(price,1))
price+= 10
var2.set(yearly)
var3.set(round(cubik,1))
yearly += 300
cubik += 0.1
time.sleep(5)
update_timeText()
root.update_idletasks()
##update_timeText()
##root.mainloop()

how to make this python code run on raspberry pi

i wrote this code and it runs perfectly on my windows pc using PyCharm.
when i run it from my raspberry pi 2 using the default interpreter it acts weird- buttons don't always respond, and alarmList array won't print properly on command.
has anyone had this problem before?
code:
import time
from Tkinter import *
import tkMessageBox
date = [time.strftime('%Y', time.localtime(time.time())), time.strftime('%m', time.localtime(time.time())), time.strftime('%d', time.localtime(time.time())), time.strftime('%H', time.localtime(time.time())), time.strftime('%M', time.localtime(time.time())), time.strftime('%S', time.localtime(time.time()))]
main = Tk()
main.overrideredirect(True)
main.grid_columnconfigure(0, weight=3)
main.grid_rowconfigure(0, weight=3)
main.geometry("{0}x{1}+0+0".format(main.winfo_screenwidth(), main.winfo_screenheight()))
AlarmList = []
def setAlarm():
def submit_alarm():
get_alarm = [int(alarm_hour_entry.get()), int(alarm_minute_entry.get())]
alarm_hour_entry.delete(0, END)
alarm_minute_entry.delete(0, END)
if get_alarm[0] > 0 and get_alarm[0] < 23 and get_alarm[1] >= 0 and get_alarm[1] < 59:
AlarmList.append(get_alarm)
AlarmList.sort()
else:
tkMessageBox.showinfo("Invalid Time", "please enter a valid time, you fucking douchebag")
print AlarmList
alarm_set = Tk()
# alarm_set.configure(bg='white')
alarm_set.overrideredirect(True)
alarm_set.geometry("{0}x{1}+0+0".format(alarm_set.winfo_screenwidth(), alarm_set.winfo_screenheight()))
alarm_hour_label = Label(alarm_set, text="Alarm Hour:")
alarm_hour_entry = Entry(alarm_set)
alarm_hour_label.grid(row=0, column=0)
alarm_hour_entry.grid(row=0, column=1)
alarm_minute_label = Label(alarm_set, text="Alarm Minute:")
alarm_minute_entry = Entry(alarm_set)
alarm_minute_label.grid(row=1, column=0)
alarm_minute_entry.grid(row=1, column=1)
submit_button = Button(alarm_set, text='submit', command=submit_alarm)
submit_button.grid(row=2, column=1)
quit_alarm = Button(alarm_set, text="back to menu", command=alarm_set.destroy)
quit_alarm.grid(row=2, column=0)
alarm_set.mainloop()
def tick():
global time1
# get the current local time from the PC
time2 = time.strftime('%H:%M:%S')
# if time string has changed, update it
if time2 != time1:
time1 = time2
clock.config(text=time2)
# calls itself every 200 milliseconds
# to update the time display as needed
# could use >200 ms, but display gets jerky
clock.after(200, tick)
button1=Button(text='Set Alarm', font=('times', 15, 'bold'), command=setAlarm, bd=0, padx=2, pady=2)
button1.config(height=10, width=50)
button1.grid(row=0, column=0, sticky=W)
quit_main=Button(main, text='quit', font=('times', 15, 'bold'), command=main.destroy, bd=0, padx=30, pady=2)
#quit_main.configure(height=10, width=20)
quit_main.grid(row=3, column=0, sticky=W)
time1 = ''
clock = Label(main, font=('times', 100, 'bold'), bg='blue', fg='white')
clock.grid(row=1, columnspan=2, sticky=N)
settings_photo=PhotoImage(file="settings.gif")
settings=Button(image=settings_photo,bd=0)
settings.grid(row=3, column=1)
tick()
main.mainloop()

Tkinter: Changing value of a Textbox after calculation to avoid duplicates

from tkinter import *
class HHRG:
def __init__(self, root):
self.root = root
self.RnReg = 50
self.RnResump = 80
self.RnCert = 80
self.RnDC = 70
self.RnSOC = 90
self.LvnReg = 40
self.LvnOut = 35
self.Hha = 25
self.Pt = 75
self.Ot = 75
self.St = 75
self.HHRGValue = IntVar()
self.RnRegValue = IntVar()
self.RnResumpValue = IntVar()
self.RnCertValue = IntVar()
self.RnDCValue = IntVar()
self.RnSOCValue = IntVar()
self.LvnRegValue = IntVar()
self.LvnOutValue = IntVar()
self.HhaValue = IntVar()
self.PtValue = IntVar()
self.OtValue = IntVar()
self.StValue = IntVar()
###LABELS###
self.HHRGLabel = Label(self.root, text="HHRG")
self.RnRegLabel = Label(self.root, text="Regular Rn Visits")
self.RnResumpLabel = Label(self.root, text="Rn Resumption Visits")
self.RnCertLabel = Label(self.root, text="Rn recertification Visits")
self.RnDCLabel = Label(self.root, text="Rn D/C Visits")
self.RnSOCLabel = Label(self.root, text="Rn SOC Visits")
self.LvnRegLabel = Label(self.root, text="Regular Lvn Visits")
self.LvnOutLabel = Label(self.root, text="Lvn Outlier Visits")
self.HhaLabel = Label(self.root, text="HHA visits")
self.PtLabel = Label(self.root, text="Pt Visits")
self.OtLabel = Label(self.root, text="Ot Visits")
self.StLabel = Label(self.root, text="St Visits")
self.TotalLabel = Label(self.root, text="Net Total")
###ENTRY BOXES###
self.HHRGEntry = Entry(self.root, textvariable=self.HHRGValue)
self.RnRegEntry = Entry(self.root, textvariable=self.RnRegValue)
self.RnResumpEntry = Entry(self.root, textvariable=self.RnResumpValue)
self.RnCertEntry = Entry(self.root, textvariable=self.RnCertValue)
self.RnDCEntry = Entry(self.root, textvariable=self.RnDCValue)
self.RnSOCEntry = Entry(self.root, textvariable=self.RnSOCValue)
self.LvnRegEntry = Entry(self.root, textvariable=self.LvnRegValue)
self.LvnOutEntry = Entry(self.root, textvariable=self.LvnOutValue)
self.HhaEntry = Entry(self.root, textvariable=self.HhaValue)
self.PtEntry = Entry(self.root, textvariable=self.PtValue)
self.OtEntry = Entry(self.root, textvariable=self.OtValue)
self.StEntry = Entry(self.root, textvariable=self.StValue)
self.TotalEntry = Text(root, height=2, width=10)
self.clearButton = Button(root, text="Clear")
self.clearButton.bind("<Button-1>", self.clear)
self.calculatebutton = Button(root, text="Calculate", width=10)
self.calculatebutton.bind("<Button-1>", self.clear)
self.calculatebutton.bind("<Button-1>", self.calculate)
####LABEL GRIDS###
self.HHRGLabel.grid(row=0, column=0)
self.RnRegLabel.grid(row=1, column=0)
self.RnResumpLabel.grid(row=2, column=0)
self.RnCertLabel.grid(row=3, column=0)
self.RnDCLabel.grid(row=4, column=0)
self.RnSOCLabel.grid(row=5, column=0)
self.LvnRegLabel.grid(row=6, column=0)
self.LvnOutLabel.grid(row=7, column=0)
self.HhaLabel.grid(row=8, column=0)
self.PtLabel.grid(row=9, column=0)
self.OtLabel.grid(row=10, column=0)
self.StLabel.grid(row=11, column=0)
self.TotalLabel.grid(row=12, column=0)
###ENTRY GRIDS###
self.HHRGEntry.grid(row=0, column=1)
self.RnRegEntry.grid(row=1, column=1)
self.RnResumpEntry.grid(row=2, column=1)
self.RnCertEntry.grid(row=3, column=1)
self.RnDCEntry.grid(row=4, column=1)
self.RnSOCEntry.grid(row=5, column=1)
self.LvnRegEntry.grid(row=6, column=1)
self.LvnOutEntry.grid(row=7, column=1)
self.HhaEntry.grid(row=8, column=1)
self.PtEntry.grid(row=9, column=1)
self.OtEntry.grid(row=10, column=1)
self.StEntry.grid(row=11, column=1)
self.TotalEntry.grid(row=12, column=1)
self.calculatebutton.grid(columnspan=2, pady=10)
self.clearButton.grid(row=13, column=1)
def calculate(self, event):
values = [(self.RnRegValue.get() * self.RnReg),
(self.RnResumpValue.get() * self.RnResump),
(self.RnCertValue.get() * self.RnCert),
(self.RnDCValue.get() * self.RnDC),
(self.RnSOCValue.get() * self.RnSOC),
(self.LvnRegValue.get() * self.LvnReg),
(self.LvnOutValue.get() * self.LvnOut),
(self.HhaValue.get() * self.Hha),
(self.PtValue.get() * self.Pt),
(self.OtValue.get() * self.Ot),
(self.StValue.get() * self.St)]
self.total = 0
for i in values:
self.total += i
result = self.HHRGValue.get() - self.total
self.TotalEntry.insert(END, result)
def clear(self, event):
self.TotalEntry.delete("1.0", END)
root = Tk()
a = HHRG(root)
root.mainloop()
So i've got this modified calculator of mine and the problem with it is everytime you calculate. it returns outputs as desired but if you click it twice
it'll duplicate
I tried binding the self.calculatebutton to my clear() method but it wouldn't prevent the duplication of the results
my question is. How can we make it calculate the desired output but wipe the previous output at the same time to prevent duplicates? so if someone presses the calculate button multiple times it'll only output one total not multiple ones like the picture above
This code is where the problem lies:
self.calculatebutton = Button(root,text="Calculate",width=10)
self.calculatebutton.bind("<Button-1>",self.clear)
self.calculatebutton.bind("<Button-1>",self.calculate)
When you call bind, it will replace any previous binding of the same event to the same widget. So, the binding to self.clear goes away when you add the binding to self.calculate. While there are ways to bind multiple functions to an event, usually that is completely unnecessary and leads to difficult-to-maintain code.
The simple solution is for your calculate function to call the clear function before adding a new result:
def calculate(self,event):
...
result = self.HHRGValue.get() - self.total
self.clear(event=None)
self.TotalEntry.insert(END,result)
Note: if this is the only time you'll call clear, you can remove the event parameter from the function definition, and remove it from the call.
On a related note: generally speaking you should not use bind on buttons. The button has built-in bindings that normally work better than your custom binding (they handle keyboard traversal and button highlighting, for example).
The button widget has a command attribute which you normally use instead of a binding. In your case it would look like this:
self.calculatebutton = Button(..., command=self.calculate)
When you do that, your calculate method no longer needs the event parameter, so you'll need to remove it. If you want to use the calculate function both from a command and from a binding, you can make the event optional:
def calculate(self, event=None)
A simple fix could be to just call your clear method in your calculate method, before inserting the text into your TotalEntry text widget.
Try this:
def calculate(self,event):
values = [(self.RnRegValue.get() * self.RnReg),
(self.RnResumpValue.get() * self.RnResump),
(self.RnCertValue.get() * self.RnCert),
(self.RnDCValue.get() * self.RnDC),
(self.RnSOCValue.get() * self.RnSOC),
(self.LvnRegValue.get() * self.LvnReg),
(self.LvnOutValue.get() * self.LvnOut),
(self.HhaValue.get() * self.Hha),
(self.PtValue.get() * self.Pt),
(self.OtValue.get() * self.Ot),
(self.StValue.get() * self.St)]
self.total = 0
for i in values:
self.total += i
result = self.HHRGValue.get() - self.total
self.clear(event)
self.TotalEntry.insert(END,result)

How to get tkinter Spinbox's value?

I am trying to make a timer on python Tkinter. To set the timer, I am using spinboxes. But, I am having trouble getting the value of my spinboxes to be turned into the variables time_h, time_m and time_s.
I have tried .get() but it is not working. When I tried printing the variables I got NameError: name 'spin_h' is not defined.
from tkinter import *
window = Tk()
window.title("Timer")
window.geometry('350x200')
hour = 0
minute = 0
second = 0
timer = (str(hour) + ':' + str(minute) + ':' + str(second))
lbl = Label(window, text=timer, font=("Arial Bold", 50))
hour_s = 0
min_s = 0
sec_s = 0
def save_time():
time_h = spin_h.get()
time_m = spin_m.get()
time_s = spin_s.get()
def new_window():
set_time = Tk()
spin_h = Spinbox(set_time, from_=0, to=10, width=5)
spin_h.grid(column=1,row=0)
spin_m = Spinbox(set_time, from_=0, to=60, width=5)
spin_m.grid(column=3,row=0)
spin_s = Spinbox(set_time, from_=0, to=60, width=5)
spin_s.grid(column=5,row=0)
h_label = Label(set_time, text='h', font=("Arial Bold", 10))
h_label.grid(column=2, row=0)
m_label = Label(set_time, text='m', font=("Arial Bold", 10))
m_label.grid(column=4, row=0)
s_label = Label(set_time, text='s', font=("Arial Bold", 10))
s_label.grid(column=6, row=0)
set_button = Button(set_time, text="Set Time", command=save_time)
set_button.grid(column=3, row=2)
btn = Button(window, text="Set Time", command=new_window)
btn.grid(column=3, row=2)
lbl.grid(column=3, row=0)
window.mainloop()
spin_h is a variable local to the new_window() function and there cannot be accessed by the save_time() function. You could declare it a global variable at the beginning of new_window() to fix that. - #Martineau (just made it into an answer instead of a comment).
Thanks Martineau

Categories

Resources