2

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!

2 Answers 2

6

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!

Sign up to request clarification or add additional context in comments.

1 Comment

I definitely appreciate the tip about using the after method, as it should be more efficient and potentially more accurate; however, you could use events to prevent freezing and crashing while still maintaining a while loop, using sleep. I actually made such a timer, but I didn't know about the after method, then. I'm hoping converting to it will allow for smaller intervals.
0

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

2 Comments

Your answer would be more useful if you provided a textual description of the changes. Otherwise a reader is forced to go line-by-line to try and figure out what you changed, or what was the main cause of the OP's code not working.
Is there a way you could do it without self?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.