Dan Alexander
Dan Alexander

Reputation: 2072

Basic timer in tkinter

I have written some code for a python timer but when ever I run it I get an error but the thing is I don't know what to do so I came here for help after I searched all over the internet for help but I couldn't find anything that matched my problem.

Here is the Error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Program Files\Python33\lib\tkinter\__init__.py", line 1475, in __call__
    return self.func(*args)
  File "C:\Users\Public\Documents\Programming\Timer.py", line 27, in start
    sec = sec + 1
UnboundLocalError: local variable 'sec' referenced before assignment

This is my code:

# Import Modules
from tkinter import *
import time

# Window Setup
root = Tk()
root.title('Timer')
root.state('zoomed')

# Timer Variables
global sec
time_sec = StringVar()
sec = 0

# Timer Start
def start():
    while 1:
        time.sleep(1)
        sec = sec + 1
        time_sec.set(sec)
        start()

# Timer Setup
Label(root,
      textvariable=time_sec,
      fg='green').pack()
Button(root,
       fg='blue',
       text='Start',
       command=start).pack()

# Program Loop
root.mainloop()

Could Anyone please help me?

Thanks In Advance!

Upvotes: 2

Views: 17240

Answers (2)

suhailvs
suhailvs

Reputation: 21680

You have to initiate global sec in start.ie:

......
# Timer Start
def start():
    global sec
    .....

you can put inside it in a class. so that you don't have to worry about the scope of variables..

from tkinter import *
import time

class App():
    def __init__(self):
        self.window = Tk() 
        self.root = Frame(self.window, height=200,width=200)
        self.root.pack() 
        self.root.pack_propagate(0) 
        self.window.title('Timer')
        self.label = Label(text="")
        self.label.pack()
        self.sec = 0
        self.timerupdate()
        self.root.mainloop()
    def timerupdate(self):
        self.sec = self.sec + 1
        self.label.configure(text=self.sec)
        self.root.after(1000, self.timerupdate)

app=App()
app.mainloop()

Upvotes: 0

user2555451
user2555451

Reputation:

You have to declare sec to be a global inside of start. Here is how to fix the error:

# Import Modules
from tkinter import *
import time

# Window Setup
root = Tk()
root.title('Timer')
root.state('zoomed')

# Timer Variables
global sec
time_sec = StringVar()
sec = 0

# Timer Start
def start():
    while 1:
        time.sleep(1)
        ### You have to declare sec as a global ###
        global sec
        sec = sec + 1
        time_sec.set(sec)
        start()

# Timer Setup
Label(root,
      textvariable=time_sec,
      fg='green').pack()
Button(root,
       fg='blue',
       text='Start',
       command=start).pack()

# Program Loop
root.mainloop()

However, this still has problems because it freezes the screen due to the while loop. A better way to build a timer with tkinter is like this:

from tkinter import *

root = Tk()
root.title('Timer')
root.state('zoomed')

sec = 0

def tick():
    global sec
    sec += 1
    time['text'] = sec
    # Take advantage of the after method of the Label
    time.after(1000, tick)

time = Label(root, fg='green')
time.pack()
Button(root, fg='blue', text='Start', command=tick).pack()

root.mainloop()

Also, some advice for the future: never use time.sleep or a while loop like that in a GUI. Take advantage of the GUI's mainloop instead. It will save many headaches of stuff freezing or crashing. Hope this helps!

Upvotes: 6

Related Questions